mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Implement onRequestClose for iOS 13+ modals (#27618)
Summary:
Starting on iOS 13, a View Controller presented modally will have a "bottom sheet" style unless it's explicitly presented full screen.
Before this, modals on iOS were only being dismissed programatically by setting `visible={false}`. However, now that the dismissal can happen on the OS side, we need a callback to be able to update the state.
This PR reuses the `onRequestClose` prop already available for tvOS and Android, and makes it work on iOS for this use case.
Should fix https://github.com/facebook/react-native/issues/26892
## Changelog
[iOS] [Added] - Add support for onRequestClose prop to Modal on iOS 13+
Pull Request resolved: https://github.com/facebook/react-native/pull/27618
Test Plan:
I tested this using the RNTester app with the Modal example:
1. Select any presentation style other than the full screen ones
2. Tap Present and the modal is presented
3. Swipe down on the presented modal until dismissed
4. Tap Present again and a second modal should be presented

Differential Revision: D19235758
Pulled By: shergin
fbshipit-source-id: c0f1d946c77ce8d1baab209eaef7eb64697851df
This commit is contained in:
committed by
Facebook Github Bot
parent
6be37d8c0a
commit
8e5fac89bb
@@ -95,7 +95,8 @@ export type Props = $ReadOnly<{|
|
||||
|
||||
/**
|
||||
* The `onRequestClose` callback is called when the user taps the hardware
|
||||
* back button on Android or the menu button on Apple TV.
|
||||
* back button on Android, the menu button on Apple TV, or a modal is dismissed
|
||||
* with a gesture on iOS 13+.
|
||||
*
|
||||
* This is required on Apple TV and Android.
|
||||
*
|
||||
|
||||
@@ -70,7 +70,8 @@ type NativeProps = $ReadOnly<{|
|
||||
|
||||
/**
|
||||
* The `onRequestClose` callback is called when the user taps the hardware
|
||||
* back button on Android or the menu button on Apple TV.
|
||||
* back button on Android, the menu button on Apple TV, or a modal is dismissed
|
||||
* with a gesture on iOS 13+.
|
||||
*
|
||||
* This is required on Apple TV and Android.
|
||||
*
|
||||
|
||||
@@ -94,7 +94,9 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
||||
return {orientation};
|
||||
}
|
||||
|
||||
@interface RCTModalHostViewComponentView () <RCTFabricModalHostViewControllerDelegate>
|
||||
@interface RCTModalHostViewComponentView () <
|
||||
RCTFabricModalHostViewControllerDelegate,
|
||||
UIAdaptivePresentationControllerDelegate>
|
||||
|
||||
@end
|
||||
|
||||
@@ -113,6 +115,7 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
||||
_viewController = [RCTFabricModalHostViewController new];
|
||||
_viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
|
||||
_viewController.delegate = self;
|
||||
_viewController.presentationController.delegate = self;
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -217,6 +220,19 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
||||
[childComponentView removeFromSuperview];
|
||||
}
|
||||
|
||||
#pragma mark - UIAdaptivePresentationControllerDelegate
|
||||
|
||||
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
|
||||
{
|
||||
if (!_eventEmitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(std::dynamic_pointer_cast<ModalHostViewEventEmitter const>(_eventEmitter));
|
||||
auto eventEmitter = std::static_pointer_cast<ModalHostViewEventEmitter const>(_eventEmitter);
|
||||
eventEmitter->onRequestClose({});
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Class<RCTComponentViewProtocol> RCTModalHostViewCls(void)
|
||||
|
||||
@@ -32,8 +32,9 @@
|
||||
@property (nonatomic, copy) NSArray<NSString *> *supportedOrientations;
|
||||
@property (nonatomic, copy) RCTDirectEventBlock onOrientationChange;
|
||||
|
||||
#if TARGET_OS_TV
|
||||
@property (nonatomic, copy) RCTDirectEventBlock onRequestClose;
|
||||
|
||||
#if TARGET_OS_TV
|
||||
@property (nonatomic, strong) RCTTVRemoteHandler *tvRemoteHandler;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
#import "RCTTVRemoteHandler.h"
|
||||
#endif
|
||||
|
||||
@interface RCTModalHostView () <UIAdaptivePresentationControllerDelegate>
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTModalHostView
|
||||
{
|
||||
__weak RCTBridge *_bridge;
|
||||
@@ -46,6 +50,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:coder)
|
||||
UIView *containerView = [UIView new];
|
||||
containerView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
|
||||
_modalViewController.view = containerView;
|
||||
_modalViewController.presentationController.delegate = self;
|
||||
_touchHandler = [[RCTTouchHandler alloc] initWithBridge:bridge];
|
||||
#if TARGET_OS_TV
|
||||
_menuButtonGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(menuButtonPressed:)];
|
||||
@@ -70,10 +75,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:coder)
|
||||
_onRequestClose(nil);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)setOnRequestClose:(RCTDirectEventBlock)onRequestClose
|
||||
{
|
||||
_onRequestClose = onRequestClose;
|
||||
#if TARGET_OS_TV
|
||||
if (_reactSubview) {
|
||||
if (_onRequestClose && _menuButtonGestureRecognizer) {
|
||||
[_reactSubview addGestureRecognizer:_menuButtonGestureRecognizer];
|
||||
@@ -81,8 +88,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:coder)
|
||||
[_reactSubview removeGestureRecognizer:_menuButtonGestureRecognizer];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)notifyForBoundsChange:(CGRect)newBounds
|
||||
{
|
||||
@@ -257,4 +264,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:coder)
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
|
||||
{
|
||||
if (_onRequestClose) {
|
||||
_onRequestClose(nil);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -108,9 +108,6 @@ RCT_EXPORT_VIEW_PROPERTY(onShow, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(identifier, NSNumber)
|
||||
RCT_EXPORT_VIEW_PROPERTY(supportedOrientations, NSArray)
|
||||
RCT_EXPORT_VIEW_PROPERTY(onOrientationChange, RCTDirectEventBlock)
|
||||
|
||||
#if TARGET_OS_TV
|
||||
RCT_EXPORT_VIEW_PROPERTY(onRequestClose, RCTDirectEventBlock)
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user