react-native-screens icon indicating copy to clipboard operation
react-native-screens copied to clipboard

FormSheet with sheetAllowedDetents: 'fitToContents' doesn't update height dynamically on Android

Open SickanK opened this issue 1 year ago • 10 comments

Description

The new native stack presentation formSheet with sheetAllowedDetents: 'fitToContents' on Android initially works correctly by adjusting to the content height. However, when the content height changes dynamically, the sheet does not update its height to match.

I had a short interaction over on X and was directed to post an issue here. Love the new formSheets, looking forward to being able to use them with dynamic height adjustment!

Steps to reproduce

  1. Create a new screen with a formSheet presentation mode and sheetAllowedDetents set to fitToContents
  2. Add content with a fixed height to the formSheet
  3. Open the formSheet from another screen
  4. Verify that the initial sheet height matches the fixed content height correctly
  5. Change the content's fixed height programmatically
  6. Observe that the sheet height remains at its initial size and does not adjust to match the new content height

Snack or a link to a repository

https://snack.expo.dev/SnPwLOzeISrX17ay1RuQY

Screens version

4.1.0

React Native version

0.76.3

Platforms

Android

JavaScript runtime

JSC

Workflow

Expo bare workflow

Architecture

Fabric (New Architecture)

Build type

Debug mode

Device

Real device

Device model

Nothing Phone (2) (Android 14)

Acknowledgements

Yes

SickanK avatar Dec 09 '24 08:12 SickanK

I heavily use https://github.com/lodev09/react-native-true-sheet for my sheets and they have the same issue regarding auto-sized sheets on Android. How to work around it there is that you also give the largest possible detent as an available size. So you would give ['fitToContents', '1.0'] or similar. This might work here to.

ljukas avatar Dec 09 '24 09:12 ljukas

My first impression is that it should be straightforward to do. Gimme few minutes

kkafar avatar Dec 10 '24 21:12 kkafar

I can make it jump to the right height, but I can't animate it properly (I don't want to animate it manually, would prefer to delegate it to the bottom sheet behaviour). Will look into it some more

kkafar avatar Dec 10 '24 21:12 kkafar

Here's PoC of the changes: https://github.com/software-mansion/react-native-screens/pull/2570

I wonder how it should work in cases where the content disappears? When you remove the view it would disappear instantly (unless you use reanimated or something) reducing the sheet size - animating in such cases would not make much sense.

Maybe better way forward would be to expose the sheet position as some kind of animated value you would be able to animate?

kkafar avatar Dec 11 '24 07:12 kkafar

Thanks for working on this!

Wouldn't the expected behavior mirror what happens when you initially open a sheet without content? What cases would the content disappear where you wouldn't want to instead e.g. close the sheet?

SickanK avatar Dec 13 '24 12:12 SickanK

I have encountered a similar issue, but using the iOS Simulator (iPhone, OS v18.2):

https://github.com/software-mansion/react-native-screens/issues/2688

RohovDmytro avatar Feb 14 '25 22:02 RohovDmytro

Same here. Commenting to follow along.

mnelabs-kevin avatar Mar 03 '25 20:03 mnelabs-kevin

@kkafar I made a patch with your suggested changes in #2570 and they work quite well. Any chance we can get this PR merged?

[email protected]

thebiltheory avatar Mar 13 '25 08:03 thebiltheory

@kkafar it doesn't work i scrollView changes it is own size

export const ScreenName: React.FC = () => {
  const [count, setCount] = useState(3)
  return (
    <ScrollView>
      {new Array(count).fill(null).map((_, index) => (
        <View
          key={index}
          style={{height: 40, backgroundColor: 'red', borderBottomWidth: 1}}
          nativeID={'someNativeId'}>
          <TouchableOpacity onPress={() => setCount(20)}>
            <Text>{index} - Some text</Text>
          </TouchableOpacity>
        </View>
      ))}
    </ScrollView>
  )
}

In this case, if you press on any item and increment the count, the ScrollView's contentSize will be triggered, but the sheet will not update its size.

sergeymild avatar Apr 10 '25 09:04 sergeymild

@kkafar it doesn't work i scrollView changes it is own size

export const ScreenName: React.FC = () => {
  const [count, setCount] = useState(3)
  return (
    <ScrollView>
      {new Array(count).fill(null).map((_, index) => (
        <View
          key={index}
          style={{height: 40, backgroundColor: 'red', borderBottomWidth: 1}}
          nativeID={'someNativeId'}>
          <TouchableOpacity onPress={() => setCount(20)}>
            <Text>{index} - Some text</Text>
          </TouchableOpacity>
        </View>
      ))}
    </ScrollView>
  )
}

In this case, if you press on any item and increment the count, the ScrollView's contentSize will be triggered, but the sheet will not update its size.

I confirm this being the case in the latest release (4.10.0)

RohovDmytro avatar Apr 10 '25 11:04 RohovDmytro