| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.car.ui.pagedrecyclerview.decorations.grid; |
| |
| import android.graphics.Canvas; |
| import android.graphics.Rect; |
| import android.graphics.drawable.Drawable; |
| import android.view.View; |
| |
| import androidx.recyclerview.widget.RecyclerView; |
| |
| /** Adds interior dividers to a RecyclerView with a GridLayoutManager. */ |
| public class GridDividerItemDecoration extends RecyclerView.ItemDecoration { |
| |
| private final Drawable mHorizontalDivider; |
| private final Drawable mVerticalDivider; |
| private int mNumColumns; |
| |
| /** |
| * Sole constructor. Takes in {@link Drawable} objects to be used as horizontal and vertical |
| * dividers. |
| * |
| * @param horizontalDivider A divider {@code Drawable} to be drawn on the rows of the grid of |
| * the |
| * RecyclerView |
| * @param verticalDivider A divider {@code Drawable} to be drawn on the columns of the grid of |
| * the |
| * RecyclerView |
| * @param numColumns The number of columns in the grid of the RecyclerView |
| */ |
| public GridDividerItemDecoration( |
| Drawable horizontalDivider, Drawable verticalDivider, int numColumns) { |
| this.mHorizontalDivider = horizontalDivider; |
| this.mVerticalDivider = verticalDivider; |
| this.mNumColumns = numColumns; |
| } |
| |
| /** |
| * Draws horizontal and/or vertical dividers onto the parent RecyclerView. |
| * |
| * @param canvas The {@link Canvas} onto which dividers will be drawn |
| * @param parent The RecyclerView onto which dividers are being added |
| * @param state The current RecyclerView.State of the RecyclerView |
| */ |
| @Override |
| public void onDrawOver(Canvas canvas, RecyclerView parent, RecyclerView.State state) { |
| drawVerticalDividers(canvas, parent); |
| drawHorizontalDividers(canvas, parent); |
| } |
| |
| /** |
| * Determines the size and location of offsets between items in the parent RecyclerView. |
| * |
| * @param outRect The {@link Rect} of offsets to be added around the child view |
| * @param view The child view to be decorated with an offset |
| * @param parent The RecyclerView onto which dividers are being added |
| * @param state The current RecyclerView.State of the RecyclerView |
| */ |
| @Override |
| public void getItemOffsets( |
| Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { |
| outRect.set( |
| 0, 0, mHorizontalDivider.getIntrinsicWidth(), |
| mHorizontalDivider.getIntrinsicHeight()); |
| } |
| |
| /** |
| * Adds horizontal dividers to a RecyclerView with a GridLayoutManager or its subclass. |
| * |
| * @param canvas The {@link Canvas} onto which dividers will be drawn |
| * @param parent The RecyclerView onto which dividers are being added |
| */ |
| private void drawHorizontalDividers(Canvas canvas, RecyclerView parent) { |
| int childCount = parent.getChildCount(); |
| int rowCount = childCount / mNumColumns; |
| int lastRowChildCount = childCount % mNumColumns; |
| |
| for (int i = 1; i < mNumColumns; i++) { |
| int lastRowChildIndex; |
| if (i < lastRowChildCount) { |
| lastRowChildIndex = i + (rowCount * mNumColumns); |
| } else { |
| lastRowChildIndex = i + ((rowCount - 1) * mNumColumns); |
| } |
| |
| View firstRowChild = parent.getChildAt(i); |
| View lastRowChild = parent.getChildAt(lastRowChildIndex); |
| |
| int dividerTop = firstRowChild.getTop(); |
| int dividerRight = firstRowChild.getLeft(); |
| int dividerLeft = dividerRight - mHorizontalDivider.getIntrinsicWidth(); |
| int dividerBottom = lastRowChild.getBottom(); |
| |
| mHorizontalDivider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom); |
| mHorizontalDivider.draw(canvas); |
| } |
| } |
| |
| public void setNumOfColumns(int numberOfColumns) { |
| mNumColumns = numberOfColumns; |
| } |
| |
| /** |
| * Adds vertical dividers to a RecyclerView with a GridLayoutManager or its subclass. |
| * |
| * @param canvas The {@link Canvas} onto which dividers will be drawn |
| * @param parent The RecyclerView onto which dividers are being added |
| */ |
| private void drawVerticalDividers(Canvas canvas, RecyclerView parent) { |
| double childCount = parent.getChildCount(); |
| double rowCount = Math.ceil(childCount / mNumColumns); |
| int rightmostChildIndex; |
| for (int i = 1; i <= rowCount; i++) { |
| // we dont want the divider on top of first row. |
| if (i == 1) { |
| continue; |
| } |
| if (i == rowCount) { |
| rightmostChildIndex = ((i - 1) * mNumColumns) - 1; |
| } else { |
| rightmostChildIndex = (i * mNumColumns) - 1; |
| } |
| |
| View leftmostChild = parent.getChildAt(mNumColumns * (i - 1)); |
| View rightmostChild = parent.getChildAt(rightmostChildIndex); |
| |
| // draws on top of each row. |
| int dividerLeft = leftmostChild.getLeft(); |
| int dividerBottom = leftmostChild.getTop(); |
| int dividerTop = dividerBottom - mVerticalDivider.getIntrinsicHeight(); |
| int dividerRight = rightmostChild.getRight(); |
| |
| mVerticalDivider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom); |
| mVerticalDivider.draw(canvas); |
| } |
| } |
| } |