From 88ce8773272a577c11fc10baadef3fe2aac85845 Mon Sep 17 00:00:00 2001 From: Anna Powolny Date: Wed, 15 Jan 2025 08:06:10 -0800 Subject: [PATCH] Fix scroll stretching Summary: During the last QE where I was testing the Primitive scroll someone reported that the scroll is taking too much space. https://fb.workplace.com/groups/litho.support/permalink/3981699508818054/ After investigating it, what seems to be wrong is again the measuring logic... We tried to create a copy of [ViewGroup.getChildMeasureSpec](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/ViewGroup.java#7030) but I didn't include the specMode variants. Before the change: **Spec:** widthSpec from spec **[1080, AT_MOST]** **Primitive:** - sizeConstraints width mode **AT_MOST** SizeConstraints[**minWidth = 0, maxWidth = 1080**, minHeight = 0, maxHeight = 1647] (what we are getting in LayoutScope.layout) - childConstraints width **[1080, EXACTLY]** SizeConstraints **[minWidth = 1080, maxWidth = 1080**, minHeight = 0, maxHeight = Infinity] (this is the result of our getChildMeasureSpec primitive call) I published next diff with force to test and let's see if all of the e2e and tests will pass Reviewed By: adityasharat Differential Revision: D68208796 fbshipit-source-id: a3f054da61afaaad451ad7577d5a115fce0fad65 --- .../widget/ExperimentalVerticalScroll.kt | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/litho-widget/src/main/java/com/facebook/litho/widget/ExperimentalVerticalScroll.kt b/litho-widget/src/main/java/com/facebook/litho/widget/ExperimentalVerticalScroll.kt index 0f4fa02975..3a11afd39d 100644 --- a/litho-widget/src/main/java/com/facebook/litho/widget/ExperimentalVerticalScroll.kt +++ b/litho-widget/src/main/java/com/facebook/litho/widget/ExperimentalVerticalScroll.kt @@ -44,6 +44,8 @@ import com.facebook.rendercore.primitives.LayoutBehavior import com.facebook.rendercore.primitives.LayoutScope import com.facebook.rendercore.primitives.PrimitiveLayoutResult import com.facebook.rendercore.primitives.ViewAllocator +import com.facebook.rendercore.toWidthSpec +import com.facebook.rendercore.utils.MeasureSpecUtils.getMode import kotlin.math.max import kotlin.math.min @@ -227,9 +229,11 @@ internal class VerticalScrollLayoutBehavior( val (minMeasureWidth, maxMeasureWidth) = getChildMeasureSize( - constraints.minWidth, constraints.maxWidth, ViewGroup.LayoutParams.MATCH_PARENT) + constraints.minWidth, + constraints.maxWidth, + ViewGroup.LayoutParams.MATCH_PARENT, + getMode(sizeConstraints.toWidthSpec())) val childConstraints = constraints.copy(minWidth = minMeasureWidth, maxWidth = maxMeasureWidth) - val layoutState = NestedLithoTree.layout( result = resolveResult, @@ -262,7 +266,12 @@ internal class VerticalScrollLayoutBehavior( /** * Equivalent to [VerticalScrollComponent.onMeasure] code calling [ViewGroup.getChildMeasureSpec] */ - private fun getChildMeasureSize(min: Int, max: Int, preferred: Int): Pair = + private fun getChildMeasureSize( + min: Int, + max: Int, + preferred: Int, + widthMode: Int + ): Pair = when { preferred >= 0 || min == max -> { // Fixed size due to fixed size layout param or fixed constraints. @@ -274,8 +283,14 @@ internal class VerticalScrollLayoutBehavior( 0 to max } preferred == ViewGroup.LayoutParams.MATCH_PARENT && max != SizeConstraints.Infinity -> { - // Match parent layout param, so we force the child to fill the available space. - max to max + if (widthMode == View.MeasureSpec.AT_MOST) { + // Match parent layout param with AT_MOST constraint, so we let the child decide its + // size. + 0 to max + } else { + // Match parent layout param, so we force the child to fill the available space. + max to max + } } else -> { // max constraint is infinite and layout param is WRAP_CONTENT or MATCH_PARENT.