如果同一款产品同时开发iPhone版本和iPad版本,会造成开发周期过长,人力物力消耗较大的情况.
为了解决这个问题,Apple推荐并给我们提供了一些方便的API来适配通用设备
- 概念
弹出框, 是应用开发中,尤其是iPad开发中非常重要的一个技术,一种特殊的modal展现效果 - 使用场景
普通modal会占满整个屏幕, 但iPad屏幕本身就很大, modal全部占据会浪费大屏幕也不利于用户体验 比如系统照片右上角的搜索 - 弹出窗对比
UIAlertView
主要用于简单的操作处理,两三个选项 确定/取消
MBProgressHUD/SVProgressHUD
主要用于提示状态,一般没有选项,自动消失
Popover
主要用于数据选择,主要为列表形式展示数据
Popover属于Modal的一种
版本变化
iOS7之前: 使用UIPopovercontroller
实现popover功能,但仅限制在iPad上使用
iOS8开始: 苹果推出UIPopoverpresentationcontroller
替代UIPopovercontroller
, 新API可以在iPad和iPhone上同时使用,简化了通用项目的开发
- 1.StoryBoard中设置Popover
1>iPad:
界面搭建:
在拖拽item到TableView控制器时,选择
Present As Popover
这样就可以在iPad上实现Popover效果了
设置Popover的大小(prepareForSegue中)
当控制器为Popover的目标控制器时,使用preferredContentSize才可以改变Popover的大小
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
UIViewController *destination = segue.destinationViewController;
destination.preferredContentSize = CGSizeMake(100, 200);
}
接下来在控制器中添加一个UIButton,也Popover到TableView控制器上,运行效果:
从图片可以看到,Popover的控制器尖尖(锚点)在UIButton的左上角处,而我们刚刚设置的UIBarButtonItem则不会出现这种问题
这是因为Popover根据产生的控件类型分为两种:UIBarButtonItem类型
和非UIBarButtonItem类型,统称为来源视图类型
来源视图类型Popover的参考点(尖尖)默认就在来源视图的左上角
并且在StoryBoard中通过拖线的方式设置Popover,系统会自动帮我们将响应的控件作为来源视图(而纯代码下必须要手动去设置来源视图/BarButtonItem)
在这个Demo中,因为同时存在两个按钮跳转同一个控制器,所以需要给两条Segue分别设置下ID进行区分
设置Popover的来源视图首先要获取到Popover对象
// 获取Popover对象
UIPopoverPresentationController *popover = destination.popoverPresentationController;
将Popover的sourceRect设置为来源视图的bounds,将会以来源视图的中心点作为参考点
// 设置参考带你
popover.sourceRect = button.bounds;
2>iPhone:
在上面的设置下,切换到iPhone上运行,默认是全屏进行展示,原因是iOS系统会modal展示进行了自适应
解决办法: 通过代理取消界面的自适应
这里需要注意,默认设置的代理遵循的协议是UIPopoverPresentationControllerDelegate
,但此代理方法中并没有我们所需要的(取消屏幕自适应),需要使用父协议UIAdaptivePresentationControllerDelegate
中的代理方法
#pragma mark - UIAdaptivePresentationControllerDelegate
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
// 取消屏幕的自适应
return UIModalPresentationNone;
}
取消自适应后,在刚刚工程基础上,iPhone便实现了Popover的效果
- 2.代码设置Popover
为了让代码更清晰,在视图构建上,还是部分采用了StoryBoard的方式,免去了UIWindow设置,直接在StoryBoard中内嵌一个导航控制,重点在于如何通过代码实现Popover效果
注意点:在纯代码下实现Popover效果,必须要手动设置来源视图或BarButtonItem两个属性,否则运行直接Crash
示例代码:
#import "ViewController.h"
@interface ViewController () <UIPopoverPresentationControllerDelegate>
@property (nonatomic,strong) UIButton *button;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.view addSubview:self.button];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Item" style:UIBarButtonItemStylePlain target:self action:@selector(clickButton:)];
}
- (void)clickButton:(id)sender {
// 创建一个目标控制
UIViewController *destination = [[UIViewController alloc] init];
destination.view.backgroundColor = [UIColor greenColor];
// 设置Popover ContentSize
destination.preferredContentSize = CGSizeMake(120, 200);
// 设置Modal类型为Popover
destination.modalPresentationStyle = UIModalPresentationPopover;
// 获取Popover对象
UIPopoverPresentationController *popover = destination.popoverPresentationController;
// 设置代理,取消自适应
popover.delegate = self;
// 来源视图
if ([sender isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)sender;
// 设置来源视图:在StoryBoard下,根据连线会自动设置来源视图或BarButtonItem,纯代码下需要手动设置,否则运行会直接崩溃
popover.sourceView = button;
// 设置参考点
popover.sourceRect = button.bounds;
} else {
// BarButtonItem
popover.barButtonItem = sender;
}
// Modal展示(Popover)
[self presentViewController:destination animated:YES completion:nil];
}
#pragma mark - UIAdaptivePresentationControllerDelegate
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
return UIModalPresentationNone;
}
#pragma mark - lazy
- (UIButton *)button {
if (_button == nil) {
_button = [[UIButton alloc] initWithFrame:CGRectMake(80, 80, 100, 40)];
_button.layer.borderColor = [UIColor purpleColor].CGColor;
_button.layer.borderWidth = 2;
_button.backgroundColor = [UIColor orangeColor];
_button.titleLabel.font = [UIFont systemFontOfSize:16];
[_button setTitle:@"button" forState:UIControlStateNormal];
[_button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[_button setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
[_button addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside];
}
return _button;
}
@end
效果图: