From 6485d14d04068c435b243cbb23e2ed581be2d246 Mon Sep 17 00:00:00 2001 From: Aleksandr Karamyshev Date: Sat, 18 Jan 2020 08:28:14 -0300 Subject: [PATCH] fix calculating size of child view, for view with size match_parent (#450) --- .../android/flexbox/FlexboxHelperTest.kt | 79 +++++++++++++++++++ .../google/android/flexbox/FlexboxHelper.java | 7 +- .../android/flexbox/FlexboxLayoutManager.java | 30 ++++++- 3 files changed, 111 insertions(+), 5 deletions(-) diff --git a/flexbox/src/androidTest/java/com/google/android/flexbox/FlexboxHelperTest.kt b/flexbox/src/androidTest/java/com/google/android/flexbox/FlexboxHelperTest.kt index 8bc8eb66..081e005c 100644 --- a/flexbox/src/androidTest/java/com/google/android/flexbox/FlexboxHelperTest.kt +++ b/flexbox/src/androidTest/java/com/google/android/flexbox/FlexboxHelperTest.kt @@ -17,6 +17,7 @@ package com.google.android.flexbox import android.view.View +import android.view.ViewGroup import android.widget.CheckBox import android.widget.TextView import androidx.core.widget.CompoundButtonCompat @@ -167,6 +168,84 @@ class FlexboxHelperTest { assertEquals(3, thirdLine.mLastIndex) } + @Test + @Throws(Throwable::class) + fun testCalculateVertical_flexWrap_wrap_flexDirection_column_viewSize_match_parent() { + val activity = activityRule.activity + val lp1 = FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 490) + val view1 = View(activity) + view1.layoutParams = lp1 + + val lp2 = FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 500) + val view2 = View(activity) + view2.layoutParams = lp2 + + val lp3 = FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 500) + val view3 = View(activity) + view3.layoutParams = lp3 + + val lp4 = FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 700) + val view4 = View(activity) + view4.layoutParams = lp4 + + val lp5 = FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 300) + val view5 = View(activity) + view5.layoutParams = lp5 + + val lp6 = FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 100) + val view6 = View(activity) + view6.layoutParams = lp6 + + flexContainer.addView(view1) + flexContainer.addView(view2) + flexContainer.addView(view3) + flexContainer.addView(view4) + flexContainer.addView(view5) + flexContainer.addView(view6) + flexContainer.flexWrap = FlexWrap.WRAP + flexContainer.flexDirection = FlexDirection.COLUMN + val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(500, View.MeasureSpec.EXACTLY) + val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY) + + flexboxHelper.ensureIndexToFlexLine(flexContainer.flexItemCount) + val result = FlexboxHelper.FlexLinesResult() + flexboxHelper.calculateVerticalFlexLines(result, widthMeasureSpec, heightMeasureSpec) + + + assertEquals(4, result.mFlexLines.size) + assertEquals(990, result.mFlexLines[0].mainSize) + assertEquals(500, result.mFlexLines[1].mainSize) + assertEquals(1000, result.mFlexLines[2].mainSize) + assertEquals(100, result.mFlexLines[3].mainSize) + assertEquals(500, result.mFlexLines[0].crossSize) + //they don't show yet + assertEquals(0, result.mFlexLines[1].crossSize) + assertEquals(0, result.mFlexLines[2].crossSize) + assertEquals(0, result.mFlexLines[3].crossSize) + + assertNotNull(flexboxHelper.mIndexToFlexLine) + assertEquals(0, flexboxHelper.mIndexToFlexLine!![0]) + assertEquals(0, flexboxHelper.mIndexToFlexLine!![1]) + assertEquals(1, flexboxHelper.mIndexToFlexLine!![2]) + assertEquals(2, flexboxHelper.mIndexToFlexLine!![3]) + assertEquals(2, flexboxHelper.mIndexToFlexLine!![4]) + assertEquals(3, flexboxHelper.mIndexToFlexLine!![5]) + + val firstLine = result.mFlexLines[0] + assertEquals(0, firstLine.mFirstIndex) + assertEquals(1, firstLine.mLastIndex) + val secondLine = result.mFlexLines[1] + assertEquals(2, secondLine.mFirstIndex) + assertEquals(2, secondLine.mLastIndex) + val thirdLine = result.mFlexLines[2] + assertEquals(3, thirdLine.mFirstIndex) + assertEquals(4, thirdLine.mLastIndex) + val fourthLine = result.mFlexLines[3] + assertEquals(5, fourthLine.mFirstIndex) + assertEquals(5, fourthLine.mLastIndex) + + } + @Test @Throws(Throwable::class) fun testDetermineMainSize_direction_row_flexGrowSet() { diff --git a/flexbox/src/main/java/com/google/android/flexbox/FlexboxHelper.java b/flexbox/src/main/java/com/google/android/flexbox/FlexboxHelper.java index 03225fc3..c8595867 100644 --- a/flexbox/src/main/java/com/google/android/flexbox/FlexboxHelper.java +++ b/flexbox/src/main/java/com/google/android/flexbox/FlexboxHelper.java @@ -540,11 +540,12 @@ void calculateFlexLines(FlexLinesResult result, int mainMeasureSpec, // so far into account. In that case, the width of the child needs to be // measured again note that we don't need to judge if the wrapping occurs // because it doesn't change the size along the main axis. + int padding = mFlexContainer.getPaddingLeft() + mFlexContainer.getPaddingRight() + + flexItem.getMarginLeft() + flexItem.getMarginRight() + + sumCrossSize; childCrossMeasureSpec = mFlexContainer.getChildWidthMeasureSpec( crossMeasureSpec, - mFlexContainer.getPaddingLeft() + mFlexContainer.getPaddingRight() - + flexItem.getMarginLeft() - + flexItem.getMarginRight() + sumCrossSize, + padding, flexItem.getWidth()); child.measure(childCrossMeasureSpec, childMainMeasureSpec); checkSizeConstraints(child, i); diff --git a/flexbox/src/main/java/com/google/android/flexbox/FlexboxLayoutManager.java b/flexbox/src/main/java/com/google/android/flexbox/FlexboxLayoutManager.java index 35bef60b..6fd8eb99 100644 --- a/flexbox/src/main/java/com/google/android/flexbox/FlexboxLayoutManager.java +++ b/flexbox/src/main/java/com/google/android/flexbox/FlexboxLayoutManager.java @@ -481,13 +481,39 @@ public void onNewFlexLineAdded(FlexLine flexLine) { @Override public int getChildWidthMeasureSpec(int widthSpec, int padding, int childDimension) { - return getChildMeasureSpec(getWidth(), getWidthMode(), padding, childDimension, + /* + The main idea that FlexboxHelper, counting size of the view + with dimension MATCH_PARENT with the idea, that new View should take place that we have on the screen. + For example screenWidth = 1080, firstFlexLineWidth = 1000. So this view will be 80 + It sounds logic, but we have a problem, when we already take all 1080px by first flexline. + FlexboxHelper don't know about size of Recycler, so it can't manage it. + So good point to check size is this place + But are we have a permission to decide this? + */ + int recyclerWidth = getWidth(); + if (childDimension == LayoutParams.MATCH_PARENT && padding == recyclerWidth) { + childDimension = recyclerWidth; + } + return getChildMeasureSpec(recyclerWidth, getWidthMode(), padding, childDimension, canScrollHorizontally()); } @Override public int getChildHeightMeasureSpec(int heightSpec, int padding, int childDimension) { - return getChildMeasureSpec(getHeight(), getHeightMode(), padding, childDimension, + /* + The main idea that FlexboxHelper, counting size of the view + with dimension MATCH_PARENT with the idea, that new View should take place that we have on the screen. + For example screenWidth = 1080, firstFlexLineWidth = 1000. So this view will be 80 + It sounds logic, but we have a problem, when we already take all 1080px by first flexline. + FlexboxHelper don't know about size of Recycler, so it can't manage it. + So good point to check size is this place + But are we have a permission to decide this? + */ + int recyclerHeight = getHeight(); + if (childDimension == LayoutParams.MATCH_PARENT && padding == recyclerHeight) { + childDimension = recyclerHeight; + } + return getChildMeasureSpec(recyclerHeight, getHeightMode(), padding, childDimension, canScrollVertically()); }