1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.car.widget; 18 19 import androidx.recyclerview.widget.GridLayoutManager; 20 import androidx.recyclerview.widget.RecyclerView; 21 import android.view.View; 22 23 /** 24 * Utility class that helps navigating in GridLayoutManager. 25 * 26 * <p>Assumes parameter {@code RecyclerView} uses {@link GridLayoutManager}. 27 * 28 * <p>Assumes the orientation of {@code GridLayoutManager} is vertical. 29 */ 30 class GridLayoutManagerUtils { GridLayoutManagerUtils()31 private GridLayoutManagerUtils() {} 32 33 /** 34 * @param parent RecyclerView that uses GridLayoutManager as LayoutManager. 35 * @return number of items in the first row in {@code RecyclerView}. 36 */ getFirstRowItemCount(RecyclerView parent)37 public static int getFirstRowItemCount(RecyclerView parent) { 38 GridLayoutManager manager = (GridLayoutManager) parent.getLayoutManager(); 39 int itemCount = parent.getAdapter().getItemCount(); 40 int spanCount = manager.getSpanCount(); 41 42 int spanSum = 0; 43 int pos = 0; 44 while (pos < itemCount && spanSum < spanCount) { 45 spanSum += manager.getSpanSizeLookup().getSpanSize(pos); 46 pos += 1; 47 } 48 // pos will be either the first item in second row, or item count when items not fill 49 // the first row. 50 return pos; 51 } 52 53 /** 54 * Returns the span index of an item. 55 */ getSpanIndex(View item)56 public static int getSpanIndex(View item) { 57 GridLayoutManager.LayoutParams layoutParams = 58 ((GridLayoutManager.LayoutParams) item.getLayoutParams()); 59 return layoutParams.getSpanIndex(); 60 } 61 62 /** 63 * Returns the span size of an item. {@code item} must be already laid out. 64 */ getSpanSize(View item)65 public static int getSpanSize(View item) { 66 GridLayoutManager.LayoutParams layoutParams = 67 ((GridLayoutManager.LayoutParams) item.getLayoutParams()); 68 return layoutParams.getSpanSize(); 69 } 70 71 /** 72 * Returns the index of the last item that is on the same row as {@code index}. 73 * 74 * @param index index of child {@code View} in {@code parent}. 75 * @param parent {@link RecyclerView} that contains the View {@code index} points to. 76 */ getLastIndexOnSameRow(int index, RecyclerView parent)77 public static int getLastIndexOnSameRow(int index, RecyclerView parent) { 78 int spanCount = ((GridLayoutManager) parent.getLayoutManager()).getSpanCount(); 79 int spanSum = GridLayoutManagerUtils.getSpanIndex(parent.getChildAt(index)); 80 for (int i = index; i < parent.getChildCount(); i++) { 81 spanSum += GridLayoutManagerUtils.getSpanSize(parent.getChildAt(i)); 82 if (spanSum > spanCount) { 83 // We have reached next row. 84 85 // Implicit constraint by grid layout manager: 86 // Initial spanSum + spanSize would not exceed spanCount, so it's safe to 87 // subtract 1. 88 return i - 1; 89 } 90 } 91 // Still have not reached row end. Assuming the list only scrolls vertically, we are at 92 // the last row. 93 return parent.getChildCount() - 1; 94 } 95 } 96