如何在 UIAlertController 外部点击时关闭 UIAlertController?
How to dismiss UIAlertController when tap outside the UIAlertController?
如何在点击 UIAlertController
外部时关闭 UIAlertController
?
我可以添加 UIAlertAction
样式 UIAlertActionStyleCancel
来关闭 UIAlertController
。
但我想添加这样的功能,当用户在 UIAlertController
之外点击时,UIAlertController
将消失。怎么做?谢谢。
添加样式为 UIAlertActionStyleCancel
的单独取消操作。这样当用户在外面点击时,你会得到回调。
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
}))
如果您正在使用 Swift :
使用 addAction(_:)
和 style:UIAlertActionStyle.Cancel
添加操作。
当您点击按钮或框架外时,将调用`处理程序。
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];
}]];
如果您的目标设备具有 iOS > 9.3 并使用 Swift 并且 preferredStyle 是 Alert 您可以使用如下代码段:
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)
}
与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)
}
UIView *alertView = self.alertController.view;
UIView *superPuperView = self.alertController.view.superview;
CGPoint tapCoord = [tap locationInView:superPuperView];
if (!CGRectContainsPoint(alertView.frame, tapCoord)) {
//dismiss alert view
}
最简单的方法:
- (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];
}
Obj-C 中最简单的方法:
UIAlertController *alert = [UIAlertController alertControllerWithTitle: ...
[self presentViewController:alert animated:YES completion:^{
[alert.view.superview addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(alertControllerBackgroundTapped)]];
}];
然后:
- (void)alertControllerBackgroundTapped
{
[self dismissViewControllerAnimated: YES
completion: nil];
}
如果您查看调试警报的超级视图,您会发现它不像向 _UIAlertControllerView.You 的 UITransitionView 添加点击手势识别器那么简单,可以改为执行此操作
[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)];
}
}
}];
- (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];
}
Swift, Xcode 9
使用取消按钮关闭 AlertController
向您的 alertController 提供操作,其中 UIAlertAction
的样式是 .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.
如果您不希望用户在调整 alertController 外部后关闭 alertController,请在当前方法完成关闭时禁用 alertController 的第一个子视图的用户交互。
self.present(alertController, animated: true) {
alertController.view.superview?.subviews[0].isUserInteractionEnabled = false
}
在 Controller 视图之外进行修饰时关闭 AlertController
如果您不想在控制器视图中使用取消按钮,并且想在控制器视图之外的用户触摸时关闭控制器,请这样做
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)
}
Swift 4:
当用户在使用 UIAlertController
创建的操作 Sheet 外部点击时关闭操作 Sheet
代码片段:
// 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)
}
在 iOS 15 上,UIAlertController
的视图层次结构似乎又发生了变化。它显示为包含控制器本身的新 UIWindow
。所以为了在外面关闭点击:
present(alertController, animated: true) { [weak self] in
guard let self = self else { return }
let dismissGesture = UITapGestureRecognizer(target: self, action: #selector(self.shouldDismiss))
self.alertController.view.window?.isUserInteractionEnabled = true
self.alertController.view.window?.addGestureRecognizer(dismissGesture)
}
和 shouldDismiss
函数:
@objc private func shouldDismiss() {
alertController.dismiss(animated: true)
}
如何在点击 UIAlertController
外部时关闭 UIAlertController
?
我可以添加 UIAlertAction
样式 UIAlertActionStyleCancel
来关闭 UIAlertController
。
但我想添加这样的功能,当用户在 UIAlertController
之外点击时,UIAlertController
将消失。怎么做?谢谢。
添加样式为 UIAlertActionStyleCancel
的单独取消操作。这样当用户在外面点击时,你会得到回调。
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
}))
如果您正在使用 Swift :
使用 addAction(_:)
和 style:UIAlertActionStyle.Cancel
添加操作。
当您点击按钮或框架外时,将调用`处理程序。
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];
}]];
如果您的目标设备具有 iOS > 9.3 并使用 Swift 并且 preferredStyle 是 Alert 您可以使用如下代码段:
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)
}
与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)
}
UIView *alertView = self.alertController.view;
UIView *superPuperView = self.alertController.view.superview;
CGPoint tapCoord = [tap locationInView:superPuperView];
if (!CGRectContainsPoint(alertView.frame, tapCoord)) {
//dismiss alert view
}
最简单的方法:
- (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];
}
Obj-C 中最简单的方法:
UIAlertController *alert = [UIAlertController alertControllerWithTitle: ...
[self presentViewController:alert animated:YES completion:^{
[alert.view.superview addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(alertControllerBackgroundTapped)]];
}];
然后:
- (void)alertControllerBackgroundTapped
{
[self dismissViewControllerAnimated: YES
completion: nil];
}
如果您查看调试警报的超级视图,您会发现它不像向 _UIAlertControllerView.You 的 UITransitionView 添加点击手势识别器那么简单,可以改为执行此操作
[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)];
}
}
}];
- (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];
}
Swift, Xcode 9
使用取消按钮关闭 AlertController
向您的 alertController 提供操作,其中 UIAlertAction
的样式是 .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.
如果您不希望用户在调整 alertController 外部后关闭 alertController,请在当前方法完成关闭时禁用 alertController 的第一个子视图的用户交互。
self.present(alertController, animated: true) {
alertController.view.superview?.subviews[0].isUserInteractionEnabled = false
}
在 Controller 视图之外进行修饰时关闭 AlertController
如果您不想在控制器视图中使用取消按钮,并且想在控制器视图之外的用户触摸时关闭控制器,请这样做
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)
}
Swift 4:
当用户在使用 UIAlertController
创建的操作 Sheet 外部点击时关闭操作 Sheet代码片段:
// 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)
}
在 iOS 15 上,UIAlertController
的视图层次结构似乎又发生了变化。它显示为包含控制器本身的新 UIWindow
。所以为了在外面关闭点击:
present(alertController, animated: true) { [weak self] in
guard let self = self else { return }
let dismissGesture = UITapGestureRecognizer(target: self, action: #selector(self.shouldDismiss))
self.alertController.view.window?.isUserInteractionEnabled = true
self.alertController.view.window?.addGestureRecognizer(dismissGesture)
}
和 shouldDismiss
函数:
@objc private func shouldDismiss() {
alertController.dismiss(animated: true)
}