react-native
react-native copied to clipboard
bugfix Android 15 Modal behavior change
Summary: When running on Android 15, content of the modal is cut-off at the bottom (content seems to overlap with bottom navigation bar and is cut-off)
- Android 15, even without building with targetSdk 35, seems to introduce behavior change so add code to handle such case
- also fix existing logic that seems like it just happened to work before but is no longer working with Android 15
- additional refactoring
- renamed: hostView -> dialogRootViewGroup
Changelog: [Android][Fixed] - Modal content cut-off at bottom on Android 15
Differential Revision: D61838294
This pull request was exported from Phabricator. Differential Revision: D61838294
This pull request was exported from Phabricator. Differential Revision: D61838294
Hi @alanleedev, I don’t think you actually need the ModalHostHelper/ShadowNode calculation anymore (maybe it was needed once?). I found this out when I wrote my own native modal component (to support Android's predictive gesture back). Updating the width/height onSizeChanged is enough to size the dialog correctly, no matter the size of any ancestor View.
Take a look at this example, where I’ve intentionally put my dialog inside a small View and when it opens it still takes up the whole screen. I’ve set an orange border on the dialog’s child View so you can see that it’s sized correctly.
const [detent, setDetent] = useState('hidden');
useEffect(() => {
setTimeout(() => {
setDetent('expanded');
}, 2000)
}, []);
<View style={{height: 200, width: 100}}>
<Sheet detent={detent} onChangeDetent={setDetent} hideable>
<View style={{backgroundColor: 'lightblue', borderColor: 'orange', borderWidth: 5, flex: 1}}/>
</Sheet>
</View>
https://github.com/user-attachments/assets/20878136-be2f-4d36-a85b-9ad0947d7c3a
@grahammendick Thanks for the tip. I was mainly trying to address issues that happens with Android 15 and trying to fix a few things on the way. Have you tested your component on Android 15 with both targetSdk set to 34 and 35? Curious to learn if you see any issues.
@alanleedev I haven't tested on Android 15. Without ModalHostHelper you're taking the size from what Android gives you rather than manually calculating. So it should work, but you never know.
This pull request was exported from Phabricator. Differential Revision: D61838294
@alanleedev I haven't tested on Android 15. Without
ModalHostHelperyou're taking the size from what Android gives you rather than manually calculating. So it should work, but you never know.
@grahammendick It seemed like helper was used since ReactModalHostView acts as a proxy container and it creates DialogRootViewGroup which may be created before the actual Dialog and set as the contentView and size may not be available.
@alanleedev Yea, sizing the dialog before it’s visible can avoid a possible flicker. But I think you’re a bit ‘lucky’ that it's possible to manually calculate the Modal's size on Android. With other native components that’s not an option. Take a custom TitleView in the Toolbar. This has to get its size from native on both Android and iOS and I don’t think you could reasonably manually calculate that? Or what about if you added custom detents to the Modal on iOS. It resizes as the user drags it and there’s a clear flicker when they let go and it settles into its new detent.
I’ve accepted these limitations when integrating native components into React Native. I don’t see how to get rid of them until synchronous native-to-js resizing lands in the new architecture.
This pull request was exported from Phabricator. Differential Revision: D61838294
This PR is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.
This PR was closed because it has been stalled for 7 days with no activity.