Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Children in a frozen ScrollView calls onLayout, but only on Android and not iOS #35

Open
tpcstld opened this issue Dec 12, 2023 · 1 comment

Comments

@tpcstld
Copy link

tpcstld commented Dec 12, 2023

When freezing a ScrollView in Android, the children of the ScrollView triggers onLayout with width, height, x, and y` all being 0. The main issue here is that it happens on only Android and not iOS. Ideally it would not happen on either platform.

Screen.Recording.2023-12-12.at.6.34.22.PM.mov

Sample code can be found here: https://github.com/tpcstld/react-native-test/tree/tpcstld/freeze-android

Steps to Repro:

  1. Open the app
  2. Click on Toggle Freeze

Observe that the last recorded height and width change on Android, but not iOS.

@AndyG
Copy link

AndyG commented Dec 14, 2023

+1. as a result of this, if you have a RecyclerView (and perhaps other virtualized list components) inside the frozen component, un-freezing can result in the list losing its scroll position because child views can change height if they are set to width: MATCH_PARENT and height: WRAP_CONTENT.

as a workaround, it is possible to override onMeasure in the child views of your list and do something like this, but it's a bit hacky and requires subclassing View on the native side:

// subclass View
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
  val parent = parent
  val shouldUseCachedMeasurements =
          parent != null && parent.measuredWidth == 0
          && View.MeasureSpec.getMode(widthMeasureSpec) == View.MeasureSpec.EXACTLY
   }

    if (shouldUseCachedMeasurements) {
        val previouslyMeasuredWidth = measuredWidth
        val previouslyMeasuredHeight = measuredHeight
        super.onMeasure(
            View.MeasureSpec.makeMeasureSpec(previouslyMeasuredWidth, View.MeasureSpec.EXACTLY),
            View.MeasureSpec.makeMeasureSpec(previouslyMeasuredHeight, View.MeasureSpec.EXACTLY),
        )
    } else {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants