am f8d4f950: am 0e05841e: resolved conflicts for merge of bcb644f8 to lmp-mr1-dev-plus-aosp
* commit 'f8d4f9500fdfd661501483884d4fc5ba18dd043e':
ISSUE-144101: change children size calculation
diff --git a/v7/recyclerview/src/android/support/v7/widget/GridLayoutManager.java b/v7/recyclerview/src/android/support/v7/widget/GridLayoutManager.java
index f64dee4..1a523a9 100644
--- a/v7/recyclerview/src/android/support/v7/widget/GridLayoutManager.java
+++ b/v7/recyclerview/src/android/support/v7/widget/GridLayoutManager.java
@@ -48,9 +48,11 @@
boolean mPendingSpanCountChange = false;
int mSpanCount = DEFAULT_SPAN_COUNT;
/**
- * The size of each span
+ * Right borders for each span.
+ * <p>For <b>i-th</b> item start is {@link #mCachedBorders}[i-1] + 1
+ * and end is {@link #mCachedBorders}[i].
*/
- int mSizePerSpan;
+ int [] mCachedBorders;
/**
* Temporary array to keep views in layoutChunk method
*/
@@ -252,7 +254,29 @@
} else {
totalSpace = getHeight() - getPaddingBottom() - getPaddingTop();
}
- mSizePerSpan = totalSpace / mSpanCount;
+ calculateItemBorders(totalSpace);
+ }
+
+ private void calculateItemBorders(int totalSpace) {
+ if (mCachedBorders == null || mCachedBorders.length != mSpanCount + 1
+ || mCachedBorders[mCachedBorders.length - 1] != totalSpace) {
+ mCachedBorders = new int[mSpanCount + 1];
+ }
+ mCachedBorders[0] = 0;
+ int sizePerSpan = totalSpace / mSpanCount;
+ int sizePerSpanRemainder = totalSpace % mSpanCount;
+ int consumedPixels = 0;
+ int additionalSize = 0;
+ for (int i = 1; i <= mSpanCount; i++) {
+ int itemSize = sizePerSpan;
+ additionalSize += sizePerSpanRemainder;
+ if (additionalSize > 0 && (mSpanCount - additionalSize) < sizePerSpanRemainder) {
+ itemSize += 1;
+ additionalSize -= mSpanCount;
+ }
+ consumedPixels += itemSize;
+ mCachedBorders[i] = consumedPixels;
+ }
}
@Override
@@ -393,10 +417,11 @@
}
}
- int spanSize = getSpanSize(recycler, state, getPosition(view));
- final int spec = View.MeasureSpec.makeMeasureSpec(mSizePerSpan * spanSize,
- View.MeasureSpec.EXACTLY);
final LayoutParams lp = (LayoutParams) view.getLayoutParams();
+ final int spec = View.MeasureSpec.makeMeasureSpec(
+ mCachedBorders[lp.mSpanIndex + lp.mSpanSize] -
+ mCachedBorders[lp.mSpanIndex],
+ View.MeasureSpec.EXACTLY);
if (mOrientation == VERTICAL) {
measureChildWithDecorationsAndMargin(view, spec, getMainDirSpec(lp.height));
} else {
@@ -413,8 +438,10 @@
for (int i = 0; i < count; i ++) {
final View view = mSet[i];
if (mOrientationHelper.getDecoratedMeasurement(view) != maxSize) {
- int spanSize = getSpanSize(recycler, state, getPosition(view));
- final int spec = View.MeasureSpec.makeMeasureSpec(mSizePerSpan * spanSize,
+ final LayoutParams lp = (LayoutParams) view.getLayoutParams();
+ final int spec = View.MeasureSpec.makeMeasureSpec(
+ mCachedBorders[lp.mSpanIndex + lp.mSpanSize] -
+ mCachedBorders[lp.mSpanIndex],
View.MeasureSpec.EXACTLY);
if (mOrientation == VERTICAL) {
measureChildWithDecorationsAndMargin(view, spec, maxMeasureSpec);
@@ -448,10 +475,10 @@
View view = mSet[i];
LayoutParams params = (LayoutParams) view.getLayoutParams();
if (mOrientation == VERTICAL) {
- left = getPaddingLeft() + mSizePerSpan * params.mSpanIndex;
+ left = getPaddingLeft() + mCachedBorders[params.mSpanIndex];
right = left + mOrientationHelper.getDecoratedMeasurementInOther(view);
} else {
- top = getPaddingTop() + mSizePerSpan * params.mSpanIndex;
+ top = getPaddingTop() + mCachedBorders[params.mSpanIndex];
bottom = top + mOrientationHelper.getDecoratedMeasurementInOther(view);
}
// We calculate everything with View's bounding box (which includes decor and margins)
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java
index fa31494..d01c4db 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java
@@ -188,6 +188,49 @@
checkForMainThreadException();
}
+ public void testCachedBorders() throws Throwable {
+ List<Config> testConfigurations = new ArrayList<Config>(mBaseVariations);
+ testConfigurations.addAll(cachedBordersTestConfigs());
+ for (Config config : testConfigurations) {
+ gridCachedBorderstTest(config);
+ }
+ }
+
+ private void gridCachedBorderstTest(Config config) throws Throwable {
+ RecyclerView recyclerView = setupBasic(config);
+ waitForFirstLayout(recyclerView);
+ final boolean vertical = config.mOrientation == GridLayoutManager.VERTICAL;
+ final int expectedSizeSum = vertical ? recyclerView.getWidth() : recyclerView.getHeight();
+ final int lastVisible = mGlm.findLastVisibleItemPosition();
+ for (int i = 0; i < lastVisible; i += config.mSpanCount) {
+ if ((i+1)*config.mSpanCount - 1 < lastVisible) {
+ int childrenSizeSum = 0;
+ for (int j = 0; j < config.mSpanCount; j++) {
+ View child = recyclerView.getChildAt(i * config.mSpanCount + j);
+ childrenSizeSum += vertical ? child.getWidth() : child.getHeight();
+ }
+ assertEquals(expectedSizeSum, childrenSizeSum);
+ }
+ }
+ removeRecyclerView();
+ }
+
+ private List<Config> cachedBordersTestConfigs() {
+ ArrayList<Config> configs = new ArrayList<Config>();
+ final int [] spanCounts = new int[]{88, 279, 741};
+ final int [] spanPerItem = new int[]{11, 9, 13};
+ for (int orientation : new int[]{VERTICAL, HORIZONTAL}) {
+ for (boolean reverseLayout : new boolean[]{false, true}) {
+ for (int i = 0 ; i < spanCounts.length; i++) {
+ Config config = new Config(spanCounts[i], orientation, reverseLayout);
+ config.mSpanPerItem = spanPerItem[i];
+ configs.add(config);
+ }
+ }
+ }
+ return configs;
+ }
+
public void testLayoutParams() throws Throwable {
layoutParamsTest(GridLayoutManager.HORIZONTAL);
removeRecyclerView();
@@ -727,6 +770,7 @@
int mSpanCount;
int mOrientation = GridLayoutManager.VERTICAL;
int mItemCount = 1000;
+ int mSpanPerItem = 1;
boolean mReverseLayout = false;
Config(int spanCount, int itemCount) {
@@ -759,11 +803,17 @@
class GridTestAdapter extends TestAdapter {
Set<Integer> mFullSpanItems = new HashSet<Integer>();
+ int mSpanPerItem = 1;
GridTestAdapter(int count) {
super(count);
}
+ GridTestAdapter(int count, int spanPerItem) {
+ super(count);
+ mSpanPerItem = spanPerItem;
+ }
+
void setFullSpan(int... items) {
for (int i : items) {
mFullSpanItems.add(i);
@@ -774,7 +824,7 @@
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
- return mFullSpanItems.contains(position) ? glm.getSpanCount() : 1;
+ return mFullSpanItems.contains(position) ? glm.getSpanCount() : mSpanPerItem;
}
});
}