From 168c1f45b110dce609d03db0193b3fde9465c081 Mon Sep 17 00:00:00 2001 From: Aleksandr Karamyshev Date: Tue, 14 Jan 2020 22:24:33 -0300 Subject: [PATCH 1/2] fix strange space at the top when FlexWrap (#522) --- .../android/flexbox/FlexboxLayoutManager.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) 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..d57624fc 100644 --- a/flexbox/src/main/java/com/google/android/flexbox/FlexboxLayoutManager.java +++ b/flexbox/src/main/java/com/google/android/flexbox/FlexboxLayoutManager.java @@ -1076,8 +1076,14 @@ private boolean updateAnchorFromPendingState(RecyclerView.State state, AnchorInf anchorInfo.mPosition = mPendingScrollPosition; anchorInfo.mFlexLinePosition = mFlexboxHelper.mIndexToFlexLine[anchorInfo.mPosition]; if (mPendingSavedState != null && mPendingSavedState.hasValidAnchor(state.getItemCount())) { - anchorInfo.mCoordinate = mOrientationHelper.getStartAfterPadding() + - savedState.mAnchorOffset; + if (isMainAxisDirectionHorizontal()) { + anchorInfo.mCoordinate = mOrientationHelper.getLayoutManager().getPaddingTop() + + savedState.mAnchorOffset; + } else { + anchorInfo.mCoordinate = mOrientationHelper.getStartAfterPadding() + + savedState.mAnchorOffset; + } + Log.d("TAG","1updsteFromPendingState.mCoordinate = " + anchorInfo.mCoordinate); anchorInfo.mAssignedFromSavedState = true; anchorInfo.mFlexLinePosition = NO_POSITION; return true; @@ -1121,7 +1127,10 @@ private boolean updateAnchorFromPendingState(RecyclerView.State state, AnchorInf } // TODO: Support reverse layout when flex wrap == FlexWrap.WRAP_REVERSE - if (!isMainAxisDirectionHorizontal() && mIsRtl) { + if (isMainAxisDirectionHorizontal()) { + anchorInfo.mCoordinate = mOrientationHelper.getLayoutManager().getPaddingTop() + + mPendingScrollPositionOffset; + } else if (mIsRtl) { anchorInfo.mCoordinate = mPendingScrollPositionOffset - mOrientationHelper.getEndPadding(); } else { @@ -1445,9 +1454,7 @@ private int layoutFlexLineMainAxisHorizontal(FlexLine flexLine, LayoutState layo int parentWidth = getWidth(); int childTop = layoutState.mOffset; - if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) { - childTop = childTop - flexLine.mCrossSize; - } + int startPosition = layoutState.mPosition; float childLeft; @@ -2878,7 +2885,10 @@ private void reset() { } private void assignCoordinateFromPadding() { - if (!isMainAxisDirectionHorizontal() && mIsRtl) { + if (isMainAxisDirectionHorizontal()) { + mCoordinate = mLayoutFromEnd? mOrientationHelper.getLayoutManager().getPaddingBottom() + : mOrientationHelper.getLayoutManager().getPaddingTop(); + } else if (!isMainAxisDirectionHorizontal() && mIsRtl) { mCoordinate = mLayoutFromEnd ? mOrientationHelper.getEndAfterPadding() : getWidth() - mOrientationHelper.getStartAfterPadding(); } else { From d773dd600774699e6e039026ad59db7092774c49 Mon Sep 17 00:00:00 2001 From: Aleksandr Karamyshev Date: Wed, 22 Jan 2020 11:16:22 -0300 Subject: [PATCH 2/2] special using of orientationHelper for NOWRAP flexWrap. Add some tests (#522) --- .../FlexboxLayoutManagerConfigChangeTest.kt | 176 ++++++++++++++++++ .../android/flexbox/FlexboxLayoutManager.java | 59 +++--- 2 files changed, 208 insertions(+), 27 deletions(-) diff --git a/flexbox/src/androidTest/java/com/google/android/flexbox/test/FlexboxLayoutManagerConfigChangeTest.kt b/flexbox/src/androidTest/java/com/google/android/flexbox/test/FlexboxLayoutManagerConfigChangeTest.kt index e21a4582..ec2ac33a 100644 --- a/flexbox/src/androidTest/java/com/google/android/flexbox/test/FlexboxLayoutManagerConfigChangeTest.kt +++ b/flexbox/src/androidTest/java/com/google/android/flexbox/test/FlexboxLayoutManagerConfigChangeTest.kt @@ -31,6 +31,7 @@ import androidx.test.filters.MediumTest import androidx.test.rule.ActivityTestRule import androidx.test.runner.AndroidJUnit4 import com.google.android.flexbox.FlexDirection +import com.google.android.flexbox.FlexWrap import com.google.android.flexbox.FlexboxLayoutManager import org.hamcrest.Matchers.`is` import org.hamcrest.core.IsNot.not @@ -100,6 +101,181 @@ class FlexboxLayoutManagerConfigChangeTest { assertThat(firstLine.mainSize, `is`(not(firstLineAfterRotation.mainSize))) } + + @Test + @FlakyTest + @Throws(Throwable::class) + fun testPaddingTop_row_nowrap_topless() { + val activity = activityRule.activity + val layoutManager = FlexboxLayoutManager(activity) + layoutManager.flexWrap = FlexWrap.NOWRAP + layoutManager.flexDirection = FlexDirection.ROW + val adapter = TestAdapter() + val topPadding = 0 + val leftPadding = 20 + activityRule.runOnUiThread{ + activity.setContentView(R.layout.recyclerview) + val recyclerView = activity.findViewById(R.id.recyclerview) + recyclerView.setPadding(leftPadding, topPadding, 0,0) + recyclerView.layoutManager = layoutManager + recyclerView.adapter = adapter + for (i in 0..20) { + var lp = createLayoutParams(activity, 80, 50) + adapter.addItem(lp) + } + } + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + + val firstChild = layoutManager.getChildAt(0)!! + val lastChild = layoutManager.getChildAt(layoutManager.childCount - 1)!! + assertThat(firstChild.top, IsEqualAllowingError.isEqualAllowingError(topPadding)) + assertThat(firstChild.left, IsEqualAllowingError.isEqualAllowingError(leftPadding)) + assertThat(lastChild.top, IsEqualAllowingError.isEqualAllowingError(topPadding)) + + activityRule.runOnUiThread { + val orientation = activity.resources.configuration.orientation + if (orientation == Configuration.ORIENTATION_PORTRAIT) { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE + } else { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } + } + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + + val firstChildAfterRotate = layoutManager.getChildAt(0)!! + val lastChildAfterRotate = layoutManager.getChildAt(layoutManager.childCount - 1)!! + assertThat(firstChildAfterRotate.top, IsEqualAllowingError.isEqualAllowingError(topPadding)) + assertThat(firstChildAfterRotate.left, IsEqualAllowingError.isEqualAllowingError(leftPadding)) + assertThat(lastChildAfterRotate.top, IsEqualAllowingError.isEqualAllowingError(topPadding)) + + activityRule.runOnUiThread { + val orientation = activity.resources.configuration.orientation + if (orientation == Configuration.ORIENTATION_PORTRAIT) { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE + } else { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } + } + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + + } + + @Test + @FlakyTest + @Throws(Throwable::class) + fun testPaddingTop_row_nowrap_leftless() { + val activity = activityRule.activity + val layoutManager = FlexboxLayoutManager(activity) + layoutManager.flexWrap = FlexWrap.NOWRAP + layoutManager.flexDirection = FlexDirection.ROW + val adapter = TestAdapter() + val topPadding = 40 + val leftPadding = 20 + activityRule.runOnUiThread{ + activity.setContentView(R.layout.recyclerview) + val recyclerView = activity.findViewById(R.id.recyclerview) + recyclerView.setPadding(leftPadding, topPadding, 0,0) + recyclerView.layoutManager = layoutManager + recyclerView.adapter = adapter + for (i in 0..20) { + var lp = createLayoutParams(activity, 80, 50) + adapter.addItem(lp) + } + } + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + + val firstChild = layoutManager.getChildAt(0)!! + val lastChild = layoutManager.getChildAt(layoutManager.childCount - 1)!! + assertThat(firstChild.top, IsEqualAllowingError.isEqualAllowingError(topPadding)) + assertThat(firstChild.left, IsEqualAllowingError.isEqualAllowingError(leftPadding)) + assertThat(lastChild.top, IsEqualAllowingError.isEqualAllowingError(topPadding)) + + activityRule.runOnUiThread { + val orientation = activity.resources.configuration.orientation + if (orientation == Configuration.ORIENTATION_PORTRAIT) { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE + } else { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } + } + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + + val firstChildAfterRotate = layoutManager.getChildAt(0)!! + val lastChildAfterRotate = layoutManager.getChildAt(layoutManager.childCount - 1)!! + assertThat(firstChildAfterRotate.top, IsEqualAllowingError.isEqualAllowingError(topPadding)) + assertThat(firstChildAfterRotate.left, IsEqualAllowingError.isEqualAllowingError(leftPadding)) + assertThat(lastChildAfterRotate.top, IsEqualAllowingError.isEqualAllowingError(topPadding)) + + activityRule.runOnUiThread { + val orientation = activity.resources.configuration.orientation + if (orientation == Configuration.ORIENTATION_PORTRAIT) { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE + } else { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } + } + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + + } + + @Test + @FlakyTest + @Throws(Throwable::class) + fun testPaddingTop_column_nowrap_topless() { + val activity = activityRule.activity + val layoutManager = FlexboxLayoutManager(activity) + layoutManager.flexWrap = FlexWrap.NOWRAP + layoutManager.flexDirection = FlexDirection.COLUMN + val adapter = TestAdapter() + val topPadding = 0 + val leftPadding = 20 + activityRule.runOnUiThread{ + activity.setContentView(R.layout.recyclerview) + val recyclerView = activity.findViewById(R.id.recyclerview) + recyclerView.setPadding(leftPadding, topPadding, 0,0) + recyclerView.layoutManager = layoutManager + recyclerView.adapter = adapter + for (i in 0..20) { + var lp = createLayoutParams(activity, 80, 50) + adapter.addItem(lp) + } + } + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + + val firstChild = layoutManager.getChildAt(0)!! + val lastChild = layoutManager.getChildAt(layoutManager.childCount - 1)!! + assertThat(firstChild.top, IsEqualAllowingError.isEqualAllowingError(topPadding)) + assertThat(firstChild.left, IsEqualAllowingError.isEqualAllowingError(leftPadding)) + assertThat(lastChild.left, IsEqualAllowingError.isEqualAllowingError(leftPadding)) + + activityRule.runOnUiThread { + val orientation = activity.resources.configuration.orientation + if (orientation == Configuration.ORIENTATION_PORTRAIT) { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE + } else { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } + } + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + + val firstChildAfterRotate = layoutManager.getChildAt(0)!! + val lastChildAfterRotate = layoutManager.getChildAt(layoutManager.childCount - 1)!! + assertThat(firstChildAfterRotate.top, IsEqualAllowingError.isEqualAllowingError(topPadding)) + assertThat(firstChildAfterRotate.left, IsEqualAllowingError.isEqualAllowingError(leftPadding)) + assertThat(lastChildAfterRotate.left, IsEqualAllowingError.isEqualAllowingError(leftPadding)) + + activityRule.runOnUiThread { + val orientation = activity.resources.configuration.orientation + if (orientation == Configuration.ORIENTATION_PORTRAIT) { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE + } else { + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } + } + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + + } + @Test @FlakyTest @Throws(Throwable::class) 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 d57624fc..6103b97a 100644 --- a/flexbox/src/main/java/com/google/android/flexbox/FlexboxLayoutManager.java +++ b/flexbox/src/main/java/com/google/android/flexbox/FlexboxLayoutManager.java @@ -1076,14 +1076,11 @@ private boolean updateAnchorFromPendingState(RecyclerView.State state, AnchorInf anchorInfo.mPosition = mPendingScrollPosition; anchorInfo.mFlexLinePosition = mFlexboxHelper.mIndexToFlexLine[anchorInfo.mPosition]; if (mPendingSavedState != null && mPendingSavedState.hasValidAnchor(state.getItemCount())) { - if (isMainAxisDirectionHorizontal()) { - anchorInfo.mCoordinate = mOrientationHelper.getLayoutManager().getPaddingTop() + - savedState.mAnchorOffset; - } else { - anchorInfo.mCoordinate = mOrientationHelper.getStartAfterPadding() + - savedState.mAnchorOffset; - } - Log.d("TAG","1updsteFromPendingState.mCoordinate = " + anchorInfo.mCoordinate); + OrientationHelper tempOrientationHelper = mFlexWrap == FlexWrap.NOWRAP? + mSubOrientationHelper + : mOrientationHelper; + anchorInfo.mCoordinate = tempOrientationHelper.getStartAfterPadding() + + savedState.mAnchorOffset; anchorInfo.mAssignedFromSavedState = true; anchorInfo.mFlexLinePosition = NO_POSITION; return true; @@ -1127,14 +1124,14 @@ private boolean updateAnchorFromPendingState(RecyclerView.State state, AnchorInf } // TODO: Support reverse layout when flex wrap == FlexWrap.WRAP_REVERSE - if (isMainAxisDirectionHorizontal()) { - anchorInfo.mCoordinate = mOrientationHelper.getLayoutManager().getPaddingTop() - + mPendingScrollPositionOffset; - } else if (mIsRtl) { + OrientationHelper tempOrientationHelper = mFlexWrap == FlexWrap.NOWRAP + ? mSubOrientationHelper + : mOrientationHelper; + if (!isMainAxisDirectionHorizontal() && mIsRtl) { anchorInfo.mCoordinate = mPendingScrollPositionOffset - - mOrientationHelper.getEndPadding(); + - tempOrientationHelper.getEndPadding(); } else { - anchorInfo.mCoordinate = mOrientationHelper.getStartAfterPadding() + anchorInfo.mCoordinate = tempOrientationHelper.getStartAfterPadding() + mPendingScrollPositionOffset; } return true; @@ -1454,7 +1451,9 @@ private int layoutFlexLineMainAxisHorizontal(FlexLine flexLine, LayoutState layo int parentWidth = getWidth(); int childTop = layoutState.mOffset; - + if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) { + childTop = childTop - flexLine.mCrossSize; + } int startPosition = layoutState.mPosition; float childLeft; @@ -1717,11 +1716,14 @@ private void updateLayoutStateToFillEnd(AnchorInfo anchorInfo, boolean fromNextL } else { mLayoutState.mInfinite = false; } + OrientationHelper orientationHelper = mFlexWrap == FlexWrap.NOWRAP + ? mSubOrientationHelper + : mOrientationHelper; if (!isMainAxisDirectionHorizontal() && mIsRtl) { mLayoutState.mAvailable = anchorInfo.mCoordinate - getPaddingRight(); } else { - mLayoutState.mAvailable = - mOrientationHelper.getEndAfterPadding() - anchorInfo.mCoordinate; + mLayoutState.mAvailable = orientationHelper.getEndAfterPadding() + - anchorInfo.mCoordinate; } mLayoutState.mPosition = anchorInfo.mPosition; mLayoutState.mItemDirection = LayoutState.ITEM_DIRECTION_TAIL; @@ -1759,11 +1761,14 @@ private void updateLayoutStateToFillStart(AnchorInfo anchorInfo, boolean fromPre } else { mLayoutState.mInfinite = false; } + OrientationHelper orientationHelper = mFlexWrap == FlexWrap.NOWRAP + ? mSubOrientationHelper + : mOrientationHelper; if (!isMainAxisDirectionHorizontal() && mIsRtl) { mLayoutState.mAvailable = mParent.getWidth() - anchorInfo.mCoordinate - - mOrientationHelper.getStartAfterPadding(); + - orientationHelper.getStartAfterPadding(); } else { - mLayoutState.mAvailable = anchorInfo.mCoordinate - mOrientationHelper + mLayoutState.mAvailable = anchorInfo.mCoordinate - orientationHelper .getStartAfterPadding(); } mLayoutState.mPosition = anchorInfo.mPosition; @@ -2885,15 +2890,15 @@ private void reset() { } private void assignCoordinateFromPadding() { - if (isMainAxisDirectionHorizontal()) { - mCoordinate = mLayoutFromEnd? mOrientationHelper.getLayoutManager().getPaddingBottom() - : mOrientationHelper.getLayoutManager().getPaddingTop(); - } else if (!isMainAxisDirectionHorizontal() && mIsRtl) { - mCoordinate = mLayoutFromEnd ? mOrientationHelper.getEndAfterPadding() - : getWidth() - mOrientationHelper.getStartAfterPadding(); + OrientationHelper tempOrientationHelper = mFlexWrap == FlexWrap.NOWRAP + ? mSubOrientationHelper + : mOrientationHelper; + if (!isMainAxisDirectionHorizontal() && mIsRtl) { + mCoordinate = mLayoutFromEnd ? tempOrientationHelper.getEndAfterPadding() + : getWidth() - tempOrientationHelper.getStartAfterPadding(); } else { - mCoordinate = mLayoutFromEnd ? mOrientationHelper.getEndAfterPadding() - : mOrientationHelper.getStartAfterPadding(); + mCoordinate = mLayoutFromEnd ? tempOrientationHelper.getEndAfterPadding() + : tempOrientationHelper.getStartAfterPadding(); } }