grahammendick / navigation

Scene-Based Navigation for React and React Native
https://grahammendick.github.io/navigation/
Apache License 2.0
571 stars 40 forks source link

Supported non-modal Bottom Sheet Component (iOS) #760

Closed grahammendick closed 8 months ago

grahammendick commented 8 months ago

When the modal prop is false, set the largestUndimmedDetentIdentifier to the expanded detent. Then iOS allows the scene behind to be interacted with while the sheet is open.

<BottomSheet modal={false}>

The tricky part is that iOS allows navigation (back and forward) without closing the sheet. From the Navigation router point of view the sheet lives with the scene so had to close it when navigating. Also decided to reopen the sheet when navigating back to the scene. Kept dismissed separate from selectedDetent. When navigating away retained the selectedDetent but set dismissed to true. Then set dismissed to false when navigating back. It helped that, when programmatically dismissing, iOS doesn't call presentationControllerDidDismiss so detent isn't changed to 'hidden'.

Even dismissing sheet on navigating is tricky. To animate the dismissal had to keep the scene in memory - it's popped when deallocated so the sheet contents disappear. Timing is hard too. Can't just dismiss in didShowViewController because it's too late. If a sheet is shown on the next scene immediately then this happens first and so dismissing in didShow would close this new sheet too. So had to dismiss when presenting a sheet and in didShow (if not presenting) - and then only present the new sheet when the dismiss completes. Also can't just clear the scene in memory in both dismissViewControllerAnimated completions - because if call dismissViewControllerAnimated while there's one already running then the completion fires immediately and so the sheet contents disappear. Had to make sure only the first dismissViewControllerAnimated clears the scene on completion.

Also supported opening multiple sheets, as long as they're opened from each other. So the sheets must be nested inside each other.

Will think about keeping sheet open across scenes if there's demand.