前言
在iOS应用程序中,我们经常看到各种各样的弹出框,比如地理信息、相册、相机、权限的弹出框,图片来源选择弹出框,信息提示弹出框,下拉弹出框等。这篇文章主要总结UIPopoverController、UIPopoverPresentationController、UIAlertView、UIActionSheet、UIAlertController的使用。
UIPopoverController
UIPopoverController是ipad上特有的界面元素,用户可以在其边界外单击来关闭它,在iOS9中被弃用,只能使用于iPad,在iPhone中奔溃!它需要一个UIViewController作为其内容,我们应该还会考虑弹出窗口的大小与显示的位置。可以提供一个CGRect指定弹出窗口的参考位置。用popoverContentSize这个属性来设置弹出框的大小。可以通过- (void)presentPopoverFromRect:(CGRect)rect inView:(UIView *)view permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated这个方法来显示窗口,UIPopoverArrowDirection表示箭头的方向
//新建一个内容控制器
InfoViewController *infoViewController = [[InfoViewController alloc] init];
UIPopoverController *popViewController = [[UIPopoverController alloc] initWithContentViewController:infoViewController];
//设置弹出窗口大小,如果屏幕画不下,会挤小的。这个值默认是320x1100
popViewController.popoverContentSize = CGSizeMake(200, 100);
//设置弹出窗口的参考位置
CGRect rect = CGRectMake(0, 0, 0, 0);
NSIndexPath *indexPath = [weakSelf.tableView indexPathForSelectedRow];
UITableViewCell *cell = [weakSelf.tableView cellForRowAtIndexPath:indexPath];
[popViewController presentPopoverFromRect:rect inView:cell permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
另一种显示的方法是- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated,这种方式依附于导航栏的UIBarButtonItem上。
//新建一个内容控制器
InfoViewController *infoViewController = [[InfoViewController alloc] init];
//用于任何容器布局子控制器,弹出窗口的原始大小来自视图控制器的此属性,如果设置了此属性那么UIPopoverController的popoverContentSize属性会失效。
infoViewController.preferredContentSize = CGSizeMake(200, 200);
UIPopoverController *popViewController = [[UIPopoverController alloc] initWithContentViewController:infoViewController];
//设置弹出窗口大小,如果屏幕画不下,会挤小的。这个值默认是320x1100
popViewController.popoverContentSize = CGSizeMake(200, 100);
/*
UIPopoverArrowDirection:箭头方向
*/
[popViewController presentPopoverFromBarButtonItem:self.navigationItem.rightBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
需要注意的是如果设置了弹出控制器的preperredContentSize属性那么UIPopoverController的popoverContentSize属性会失效,另外UIPopoverController有如下几个代理方法:
用来决定用户点击了蒙版后,popoverController是否可以dismiss,返回YES代表可以,返回NO代表不可以
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
UIPopoverController消失的时候调用
-(void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
UIPopoverController的位置改变的时候调用(如竖屏变横屏)
-(void)popoverController:(UIPopoverController *)popoverController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView * __nonnull * __nonnull)view
UIPopoverController还有两个比较有用的属性,isPopoverVisible属性是只读的,用于判断是否弹出控制器。还有一个passthroughViews属性,默认情况下,UIPopoverController弹出后不允许用户交互任何视图弹出框外面。passthroughViews属性允许指定的数组UIView的实例允许用户交互。
//判断是否弹出控制器
if (weakSelf.popoverController.isPopoverVisible) {
[weakSelf.popoverController dismissPopoverAnimated:YES];
}
else
{
//设置弹出窗口大小,如果屏幕画不下,会挤小的。这个值默认是320x1100
//popViewController.popoverContentSize = CGSizeMake(200, 100);
//设置弹出窗口的参考位置
CGRect rect = CGRectMake(0, 0, 0, 0);
NSIndexPath *indexPath = [weakSelf.tableView indexPathForSelectedRow];
UITableViewCell *cell = [weakSelf.tableView cellForRowAtIndexPath:indexPath];
//设置可交互的预留控件
popViewController.passthroughViews = @[cell];
/*
UIPopoverArrowDirection:箭头方向
*/
[popViewController presentPopoverFromRect:rect inView:cell permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}
UIPopoverPresentationController
UIPopoverPresentationController适用于iPhone和ipad,不过在iPhone上展现形式就为普通的模态视图,而不是弹窗的形式。UIPopoverPresentationController是UIViewController实例的属性,不需要创建,获取就可以啦。它同样需要一个UIViewController作为其内容,通过设置UIViewController实例的modalPresentationStyle的这个属性为UIModalPresentationPopover来使用UIPopoverPresentationController,还有就是它是通过- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion 方法来显示的。其他使用方式和UIPopoverController基本差不多,列如:
sourceView属性设置所依附的控件、
sourceRect属性设置弹出窗口对所依附的控件的参考位置、
permittedArrowDirections属性设置箭头方向、
passthroughViews属性设置可交互的预留控件
//新建一个内容控制器
InfoViewController *infoViewController = [InfoViewController infoViewController];
//用于任何容器布局子控制器,弹出窗口的原始大小来自视图控制器的此属性,如果设置了此属性那么UIPopoverController的popoverContentSize属性会失效。
infoViewController.preferredContentSize = CGSizeMake(200, 200);
//设置模态视图弹出的样式
[infoViewController setModalPresentationStyle:UIModalPresentationPopover];
//取出点击的cell
NSIndexPath *indexPath = [weakSelf.tableView indexPathForSelectedRow];
UITableViewCell *cell = [weakSelf.tableView cellForRowAtIndexPath:indexPath];
//UIPopoverPresentationController是UIViewController实例的属性,不需要创建,获取就可以啦
UIPopoverPresentationController *presentationCtr = infoViewController.popoverPresentationController;
//设置弹出窗口所依附的控件
presentationCtr.sourceView = cell;
//设置弹出窗口对所依附的控件的参考位置
presentationCtr.sourceRect = CGRectMake(10, 10, 20, 20);
//设置箭头方向
presentationCtr.permittedArrowDirections = UIPopoverArrowDirectionLeft;
//设置代理
presentationCtr.delegate = weakSelf;
//弹出模态视图
[weakSelf presentViewController:infoViewController animated:YES completion:nil];
//新建一个内容控制器
InfoViewController *infoViewController = [InfoViewController infoViewController];
//用于任何容器布局子控制器,弹出窗口的原始大小来自视图控制器的此属性,如果设置了此属性那么UIPopoverController的popoverContentSize属性会失效。
infoViewController.preferredContentSize = CGSizeMake(200, 200);
//设置模态视图弹出的样式
[infoViewController setModalPresentationStyle:UIModalPresentationPopover];
//UIPopoverPresentationController是UIViewController实例的属性,不需要创建,获取就可以啦
UIPopoverPresentationController *presentationCtr = infoViewController.popoverPresentationController;
//设置所依附的UIBarButtonItem
presentationCtr.barButtonItem = weakSelf.navigationItem.rightBarButtonItem;
//设置箭头方向
presentationCtr.permittedArrowDirections = UIPopoverArrowDirectionUp;
//设置代理
presentationCtr.delegate = weakSelf;
//弹出模态视图
[weakSelf presentViewController:infoViewController animated:YES completion:nil];
if (weakSelf.presentedViewController) {
[weakSelf dismissViewControllerAnimated:YES completion:nil];
}
else
{
//新建一个内容控制器
InfoViewController *infoViewController = [InfoViewController infoViewController];
//用于任何容器布局子控制器,弹出窗口的原始大小来自视图控制器的此属性,如果设置了此属性那么UIPopoverController的popoverContentSize属性会失效。
infoViewController.preferredContentSize = CGSizeMake(200, 200);
//设置模态视图弹出的样式
[infoViewController setModalPresentationStyle:UIModalPresentationPopover];
//UIPopoverPresentationController是UIViewController实例的属性,不需要创建,获取就可以啦
UIPopoverPresentationController *presentationCtr = infoViewController.popoverPresentationController;
//设置所依附的UIBarButtonItem
presentationCtr.barButtonItem = weakSelf.navigationItem.rightBarButtonItem;
//设置箭头方向
presentationCtr.permittedArrowDirections = UIPopoverArrowDirectionUp;
//设置代理
presentationCtr.delegate = weakSelf;
//取出点击的cell
NSIndexPath *indexPath = [weakSelf.tableView indexPathForSelectedRow];
UITableViewCell *cell = [weakSelf.tableView cellForRowAtIndexPath:indexPath];
//设置可交互的预留控件
presentationCtr.passthroughViews = @[cell];
//弹出模态视图
[weakSelf presentViewController:infoViewController animated:YES completion:nil];
}
UIPopoverPresentationControllerDelegate有如下四个方法:
将要弹出的时候调用
-(void)prepareForPopoverPresentation:(UIPopoverPresentationController *)popoverPresentationController
在这个方法中设置是否允许消失
-(BOOL)popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController
已经消失的时候调用
-(void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController
用到其他UIView或者CGRect的时候调用
-(void)popoverPresentationController:(UIPopoverPresentationController *)popoverPresentationController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView *__autoreleasing _Nonnull *)view
UIAlertView
UIAlertView 在iOS9中被弃用,是以弹出选择框的形式展现,在iPhone和ipad中都能适用,并且展示效果一致。它的使用十分简单:
-(instancetype)initWithTitle:(nullable NSString )title message:(nullable NSString )message delegate:(nullable id /<UIAlertViewDelegate>/)delegate cancelButtonTitle:(nullable NSString *)cancelButtonTitle otherButtonTitles:(nullable NSString *)otherButtonTitles, ... 使用这个初始化方法可以设置标题,提示信息,代理对象和操作按钮。
-(NSInteger)addButtonWithTitle:(nullable NSString *)title 这个方法添加按钮。
-(nullable UITextField *)textFieldAtIndex:(NSInteger)textFieldIndex 这个方法获取
-(void)show 这个方法用来显示UIAlertView
numberOfButtons 这个属性获取按钮的序号
visible 这个属性是用来获知是否显示的
alertViewStyle 这个属性用来设置样式的,UIAlertView有如下4中样式:
- UIAlertViewStyleDefault 默认样式,没有熟人框
- UIAlertViewStyleSecureTextInput 有一个密码输入框
- UIAlertViewStylePlainTextInput 有一个普通文本输入框
- UIAlertViewStyleLoginAndPasswordInput 有一个普通文本输入框和一个密码输入框
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"选择" message:@"请选择一个数!" delegate:weakSelf cancelButtonTitle:@"取消" otherButtonTitles:nil];
for (int index = 0; index < 100; index++) {
[alertView addButtonWithTitle:[NSString stringWithFormat:@"%i", index]];
}
[alertView show];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"登录" message:@"请输入账号和密码!" delegate:weakSelf cancelButtonTitle:@"取消" otherButtonTitles:@"登录", nil];
[alertView setAlertViewStyle:UIAlertViewStyleLoginAndPasswordInput];
UITextField * firstTextField = [alertView textFieldAtIndex:0];
firstTextField.placeholder = @"请输入账号!";
UITextField * secondTextField = [alertView textFieldAtIndex:1];
secondTextField.placeholder = @"请输入密码!";
[alertView show];
UIAlertView有如下几个代理方法
在点击按钮的时候触发,buttonIndex为点击的按钮序号
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
在将要显示的时候触发
-(void)willPresentAlertView:(UIAlertView *)alertView
在已经显示的时候触发
-(void)didPresentAlertView:(UIAlertView *)alertView
在将要消失的时候触发
-(void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
在已经消失的时候触发
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
在编辑文本框后触发
-(BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView NS_DEPRECATED_IOS(2_0, 9_0);
UIActionSheet
在iOS9中被弃用,在iPhone和ipad中都能适用,但展示效果不一致。它的使用也非常简单:
-(instancetype)initWithTitle:(nullable NSString *)title delegate:(nullable id<UIActionSheetDelegate>)delegate cancelButtonTitle:(nullable NSString *)cancelButtonTitle destructiveButtonTitle:(nullable NSString *)destructiveButtonTitle otherButtonTitles:(nullable NSString *)otherButtonTitles, ... 这个初始化方法设置标题,代理对象,信息,取消按钮和其他按钮等
-(void)showFromToolbar:(UIToolbar *)view 从UIToolbar弹出
-(void)showFromTabBar:(UITabBar *)view 从UITabBar弹出
-(void)showFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated 从UIBarButtonItem弹出
-(void)showFromRect:(CGRect)rect inView:(UIView *)view animated:(BOOL)animated 从UIView弹出
-(void)showInView:(UIView *)view 在UIView上弹出
说明:使用上述弹出方法iPhone上只有一种弹出效果,ipad可以有不同的弹出效果
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"图片来源" delegate:weakSelf cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"相机", @"相册", nil];
[actionSheet showFromTabBar:weakSelf.tabBarController.tabBar];
在点击按钮的时候触发,buttonIndex为点击的按钮序号
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
在将要弹出的时候触发 - (void)willPresentActionSheet:(UIActionSheet *)actionSheet
在已经弹出的时候触发 - (void)didPresentActionSheet:(UIActionSheet *)actionSheet
在将要消失的时候触发 - (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex
在已经消失的时候触发 - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
UIAlertController
UIAlertController 在iOS8中提供,在iPhone和ipad中都能适用,但展示效果不完全一致。它的使用也十分简单:
- (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(UIAlertControllerStyle)preferredStyle 这个工厂方法,创建UIAlertController实例并设置相关属性
UIAlertController 有两种风格:
UIAlertControllerStyleAlert,和UIAlertView的样式一致
UIAlertControllerStyleActionSheet,和UIActionSheet的样式一致,在ipad中是通过UIPopoverPresentationController弹出的,所以需要设置UIPopoverPresentationController的相关属性,否则会出错。
- (void)addAction:(UIAlertAction *)action 添加UIAlertAction对象
- (void)addTextFieldWithConfigurationHandler:(void (^ __nullable)(UITextField *textField))configurationHandler 添加UITextField,这能为UIAlertControllerStyleAlert这个样式时才能添加UITextField
title 标题
message 展示信息
preferredStyle 弹出风格
actions 这个只读属性为添加UIAlertAction对象数组
textFields 这个只读属性为添加UITextField对象数组
UIAlertAction对象,就相当于按钮的包装:
- (instancetype)actionWithTitle:(nullable NSString *)title style:(UIAlertActionStyle)style handler:(void (^ __nullable)(UIAlertAction *action))handler 这个工厂方法创建UIAlertAction对象,并初始化标题,样式,和点击操作的block
title 标题
style 样式
UIAlertActionStyleDefault 默认样式
UIAlertActionStyleCancel 取消样式
UIAlertActionStyleDestructive 严重操作样式,为红色的
enabled 是否可用
//创建UIAlertController 设置标题,信息,样式
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"登录" message:@"请输入账号密码!" preferredStyle:UIAlertControllerStyleAlert];
//添加UITextField
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.placeholder = @"请输入账号!";
//为UITextField添加监听事件
[textField addTarget:weakSelf action:@selector(textFieldChane:) forControlEvents:UIControlEventEditingChanged];
}];
//添加UITextField
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.placeholder = @"请输入密码!";
//为UITextField添加监听事件
[textField addTarget:weakSelf action:@selector(textFieldChane:) forControlEvents:UIControlEventEditingChanged];
}];
//创建UIAlertAction对象,设置标题并添加到UIAlertController上
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDestructive handler:nil];
[alertController addAction:cancelAction];
UIAlertAction *loginAction = [UIAlertAction actionWithTitle:@"登录" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}];
//设置UIAlertAction对象是否可用
loginAction.enabled = NO;
[alertController addAction:loginAction];
//展现UIAlertController
[weakSelf presentViewController:alertController animated:YES completion:nil];
//创建UIAlertController 设置标题,信息,样式
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"图片来源" message:@"请添加图片!" preferredStyle:UIAlertControllerStyleActionSheet];
//创建UIAlertAction对象,设置标题并添加到UIAlertController上
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
[alertController addAction:cancelAction];
UIAlertAction *photpAction = [UIAlertAction actionWithTitle:@"相册" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}];
[alertController addAction:photpAction];
UIAlertAction *cameraAction = [UIAlertAction actionWithTitle:@"相机" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}];
[alertController addAction:cameraAction];
if (IS_IPHONE) {
}
else
{
//如果在ipad上运行需要设置UIPopoverPresentationController的相关属性
UIPopoverPresentationController *popoverPresentCtr = alertController.popoverPresentationController;
popoverPresentCtr.barButtonItem = weakSelf.navigationItem.rightBarButtonItem;
}
//展现UIAlertController
[weakSelf presentViewController:alertController animated:YES completion:nil];