Skip to content

Commit

Permalink
fix(iOS): invalid orientation of contained modals (#2011)
Browse files Browse the repository at this point in the history
## Description

On iOS there's a bug with contained (and contained transparent) modals,
where the modal does not change its orientation when the whole interface
(and/or device) is being rotated.
That's because contained modals will keep its orientation when the
interface is being rotated, as their controllers don't update the bounds
-> `viewDidLayoutSubviews` and `updateBounds` methods were not called at
the moment of changing the orientation.

This PR fixes this bug by updating the bounds when `layoutSubviews`
method from RNSScreenStack is being called, meaning that no matter if
there were previously any modals that have been dismissed or not, screen
stack will always update the bounds of the modal views.

Fixes #2006.

## Changes

- Fixed the problem with invalid orientation of contained modals by
updating their bounds.

## Screenshots / GIFs

### Before


https://github.com/software-mansion/react-native-screens/assets/23281839/069a2df7-ebb6-4de5-b8be-d5e1d045421b


### After


https://github.com/software-mansion/react-native-screens/assets/23281839/c3cbd102-4c68-4749-b2a0-4eaba6b8703f

## Test code and steps to reproduce

You can use Test2008 from TestsExample and FabricTestExample to test the
change from this PR.

## Checklist

- [X] Included code example that can be used to test this change
- [x] Ensured that CI passes
  • Loading branch information
tboba committed Jan 24, 2024
1 parent fc806f8 commit d460f1d
Showing 1 changed file with 16 additions and 0 deletions.
16 changes: 16 additions & 0 deletions ios/RNSScreenStack.mm
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,22 @@ - (void)layoutSubviews
{
[super layoutSubviews];
_controller.view.frame = self.bounds;

// We need to update the bounds of the modal views here, since
// for contained modals they are not updated by modals themselves.
for (UIViewController *modal in _presentedModals) {
// Because `layoutSubviews` method is also called on grabbing the modal,
// we don't want to update the frame when modal is being dismissed.
// We also want to get the frame in correct position. In the best case, it
// should be modal's superview (UITransitionView), which frame is being changed correctly.
// Otherwise, when superview is nil, we will fallback to the bounds of the ScreenStack.
BOOL isModalBeingDismissed = [modal isKindOfClass:[RNSScreen class]] && ((RNSScreen *)modal).isBeingDismissed;
CGRect correctFrame = modal.view.superview != nil ? modal.view.superview.frame : self.bounds;

if (!CGRectEqualToRect(modal.view.frame, correctFrame) && !isModalBeingDismissed) {
modal.view.frame = correctFrame;
}
}
}

- (void)dismissOnReload
Expand Down

0 comments on commit d460f1d

Please sign in to comment.