问题
How to dismiss UIAlertController
when tap outside the UIAlertController
?
I can add a UIAlertAction
of style UIAlertActionStyleCancel
to dismiss the UIAlertController
.
But I want to add the function that when user tap outside the UIAlertController
the UIAlertController
will dismiss. How to do that? Thank you.
回答1:
Add a separate cancel action with style UIAlertActionStyleCancel
. So that when user taps outside, you would get the callback.
Obj-c
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Alert Title" message:@"A Message" preferredStyle:UIAlertControllerStyleActionSheet];
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
// Called when user taps outside
}]];
Swift 5.0
let alertController = UIAlertController(title: "Alert Title", message: "A Message", preferredStyle: .actionSheet)
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: {
action in
// Called when user taps outside
}))
回答2:
If you are targeting devices having iOS > 9.3 and using Swift and preferredStyle is Alert you can use snippet as below:
func showAlertBtnClicked(sender: UIButton) {
let alert = UIAlertController(title: "This is title", message: "This is message", preferredStyle: .Alert)
self.presentViewController(alert, animated: true, completion:{
alert.view.superview?.userInteractionEnabled = true
alert.view.superview?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.alertControllerBackgroundTapped)))
})
}
func alertControllerBackgroundTapped()
{
self.dismissViewControllerAnimated(true, completion: nil)
}
With swift 3:
func showAlertBtnClicked(sender: UIButton) {
let alert = UIAlertController(title: "This is title", message: "This is message", preferredStyle: .alert)
self.present(alert, animated: true) {
alert.view.superview?.isUserInteractionEnabled = true
alert.view.superview?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.alertControllerBackgroundTapped)))
}
}
func alertControllerBackgroundTapped()
{
self.dismiss(animated: true, completion: nil)
}
回答3:
Swift, Xcode 9
Dismiss AlertController with cancel button
provide action to your alertController where UIAlertAction
's style is .cancel
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(cancelAction)
Using this method alertController will be dismissed when user will tap to cancel action button as well as outside of the alertController.
if you don't want user to dismiss alertController after touch up outside of alertController, disable user interaction of first subviews of alertController in completion closure of present method.
self.present(alertController, animated: true) {
alertController.view.superview?.subviews[0].isUserInteractionEnabled = false
}
Dismiss AlertController on touchup outside of Controller view
If you don't want cancel button in your controller view and want to dismiss controller when user touchup outside of controller view, do so
self.present(alertController, animated: true) {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissAlertController))
alertController.view.superview?.subviews[0].addGestureRecognizer(tapGesture)
}
@objc func dismissAlertController(){
self.dismiss(animated: true, completion: nil)
}
回答4:
If you are using Swift :
Add an action with addAction(_:)
and style:UIAlertActionStyle.Cancel
.
The `handler will be called when ou tap on the button or outside the frame.
var alertVC = UIAlertController(...) // initialize your Alert View Controller
alertVC.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: {
(alertAction: UIAlertAction!) in
alertVC.dismissViewControllerAnimated(true, completion: nil)
}))
Objective-C :
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:...];
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
[alertVC dismissViewControllerAnimated:YES completion:nil];
}]];
回答5:
The easiest way in Obj-C:
UIAlertController *alert = [UIAlertController alertControllerWithTitle: ...
[self presentViewController:alert animated:YES completion:^{
[alert.view.superview addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(alertControllerBackgroundTapped)]];
}];
and then:
- (void)alertControllerBackgroundTapped
{
[self dismissViewControllerAnimated: YES
completion: nil];
}
回答6:
- (void)addBackgroundDismissTapForAlert:(UIAlertController *)alert {
if (!alert.view.superview) {
return;
}
alert.view.superview.userInteractionEnabled = YES;
[alert.view.superview addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget: self action: @selector(alertControllerBackgroundTapped)]];
for (UIView *subV in alert.view.superview.subviews) {
if (subV.width && subV.height) {
subV.userInteractionEnabled = YES;
[subV addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget: self action: @selector(alertControllerBackgroundTapped)]];
}
}
}
- (void)alertControllerBackgroundTapped {
[self dismissViewControllerAnimated: YES
completion: nil];
}
回答7:
Swift 4:
Dismiss Action Sheet when User Taps outside Action Sheet created using UIAlertController
Code Snippet:
// Declare Action Sheet reference
var actionSheet: UIAlertController!
// Init and Show Action Sheet
func showActionSheetClicked(sender: UIButton) {
// Init Action Sheet
actionSheet = UIAlertController(title: "Title", message: "Message", preferredStyle: .actionSheet)
self.present(actionSheet, animated: true) {
// Enabling Interaction for Transperent Full Screen Overlay
self.actionSheet.view.superview?.subviews.first?.isUserInteractionEnabled = true
// Adding Tap Gesture to Overlay
self.actionSheet.view.superview?.subviews.first?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.actionSheetBackgroundTapped)))
}
}
// To dismiss Action Sheet on Tap
@objc func actionSheetBackgroundTapped() {
self.actionSheet.dismiss(animated: true, completion: nil)
}
回答8:
UIView *alertView = self.alertController.view;
UIView *superPuperView = self.alertController.view.superview;
CGPoint tapCoord = [tap locationInView:superPuperView];
if (!CGRectContainsPoint(alertView.frame, tapCoord)) {
//dismiss alert view
}
回答9:
The simplest way:
- (void)viewDidLoad {
[super viewDidLoad];
[self button];
}
- (void) button {
UIButton * AlertButton = [UIButton buttonWithType:UIButtonTypeSystem];
[AlertButton setTitle:@"Button" forState:UIControlStateNormal];
AlertButton.frame = CGRectMake((self.view.frame.size.width/2) - 50 , (self.view.frame.size.height/2) - 25, 100, 50);
[AlertButton addTarget:self action:@selector(Alert) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:AlertButton];
}
- (void)Alert {
UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"Alert Title" message:@"Alert Message" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController: alert animated: YES completion:^{ alert.view.superview.userInteractionEnabled = YES; [alert.view.superview addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget: self action: @selector(DismissAlertByTab)]]; }];
}
- (void)DismissAlertByTab
{
[self dismissViewControllerAnimated: YES completion: nil];
}
回答10:
If you view debug the superview of the alert, you see its not as simple as adding a tap gesture recognizer to the UITransitionView of the _UIAlertControllerView.You can do this instead
[presenter presentViewController:alertController animated:YES completion:^{
NSArray <UIView *>* superviewSubviews = alertController.view.superview.subviews;
for (UIView *subview in superviewSubviews) {
if (CGRectEqualToRect(subview.bounds, weakSelf.view.bounds)) {
[subview addSingleTapGestureWithTarget:weakSelf action:@selector(dismissModalTestViewController)];
}
}
}];
来源:https://stackoverflow.com/questions/30075832/how-to-dismiss-uialertcontroller-when-tap-outside-the-uialertcontroller