Popover

作者: ShenYj | 来源:发表于2016-09-22 13:09 被阅读908次

如果同一款产品同时开发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:

界面搭建:

UI.png
在拖拽item到TableView控制器时,选择Present As Popover
as popover.png

这样就可以在iPad上实现Popover效果了


iPad default.png

设置Popover的大小(prepareForSegue中)
当控制器为Popover的目标控制器时,使用preferredContentSize才可以改变Popover的大小

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    
    UIViewController *destination = segue.destinationViewController;
    
    destination.preferredContentSize = CGSizeMake(100, 200);
    
}
perferredContentSize.png

接下来在控制器中添加一个UIButton,也Popover到TableView控制器上,运行效果:


button default.png

从图片可以看到,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;
设置参考点.png
2>iPhone:

在上面的设置下,切换到iPhone上运行,默认是全屏进行展示,原因是iOS系统会modal展示进行了自适应

解决办法: 通过代理取消界面的自适应

这里需要注意,默认设置的代理遵循的协议是UIPopoverPresentationControllerDelegate,但此代理方法中并没有我们所需要的(取消屏幕自适应),需要使用父协议UIAdaptivePresentationControllerDelegate中的代理方法

#pragma mark - UIAdaptivePresentationControllerDelegate
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
    // 取消屏幕的自适应
    return UIModalPresentationNone;
}

取消自适应后,在刚刚工程基础上,iPhone便实现了Popover的效果


Iphone 取消自适应.png
  • 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

效果图:


代码Popover.png

相关文章

网友评论

    本文标题:Popover

    本文链接:https://www.haomeiwen.com/subject/lqrzettx.html