iOS开发中UIPopoverController的使用详解

男兒當自強4

男兒當自強4

2016-02-19 10:59

给自己一点时间接受自己,爱自己,趁着下午茶的时间来学习图老师推荐的iOS开发中UIPopoverController的使用详解,过去的都会过去,迎接崭新的开始,释放更美好的自己。

一、简单介绍

1.什么是UIPopoverController

是iPad开发中常见的一种控制器(在iPhone上不允许使用)

跟其他控制器不一样的是,它直接继承自NSObject,并非继承自UIViewController

它只占用部分屏幕空间来呈现信息,而且显示在屏幕的最前面

2.使用步骤

要想显示一个UIPopoverController,需要经过下列步骤

(1)设置内容控制器

  由于UIPopoverController直接继承自NSObject,不具备可视化的能力。因此UIPopoverController上面的内容必须由另外一个继承自UIViewController的控制器来提供,这个控制器称为“内容控制器”

 (2)设置内容的尺寸

  显示出来占据多少屏幕空间

(3)显示,即从哪个地方冒出来

二、具体的步骤

代码示例:

新建一个ipad项目,编写如下代码: 

新建一个继承自UITableView的控制器,让其作为popoverController的内容控制器。

YYMenuViewController.m文件
代码如下:

//
//  YYMenuViewController.m
//  01-PopoverController简单介绍
//
//  Created by apple on 14-8-17.
//  Copyright (c) 2014年 yangyong. All rights reserved.
//

#import "YYMenuViewController.h"

@interface YYMenuViewController ()
@property(nonatomic,strong)NSArray *menus;
@end

代码如下:

@implementation YYMenuViewController

-(NSArray *)menus
{
    if (_menus==nil) {
        _menus=@[@"列表1",@"列表2",@"列表3",@"列表4"];
    }
 return _menus;
}
- (void)viewDidLoad
{
    [super viewDidLoad];
}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.menus.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID=@"ID";
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];
    if (cell==nil) {
        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
   
    cell.textLabel.text=self.menus[indexPath.row];
    return cell;
}

@end

代码如下:

YYViewController.m文件
//
//  YYViewController.m
//  01-PopoverController简单介绍
//
//  Created by apple on 14-8-17.
//  Copyright (c) 2014年 yangyong. All rights reserved.
//

#import "YYViewController.h"
#import "YYMenuViewController.h"

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

@interface YYViewController ()
@property(nonatomic,strong)UIPopoverController *popover;
@end

@implementation YYViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //1.新建一个内容控制器
    YYMenuViewController *menuVc=[[YYMenuViewController alloc]init];
   
    //2.新建一个popoverController,并设置其内容控制器
    self.popover=[[UIPopoverController alloc]initWithContentViewController:menuVc];
   
    //3.设置尺寸
    self.popover.popoverContentSize=CGSizeMake(300, 200);
   
    //4.显示
    [self.popover presentPopoverFromBarButtonItem:self.navigationItem.leftBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
@end

实现效果如下图:

说明:在storyboard中添加了导航控制器,并添加了两个按钮。

三、常见报错

在popover的使用过程中,经常会遇到这个错误
代码如下:

  -[UIPopoverController dealloc] reached while popover is still visible.

错误的大体意思是:popover在仍旧可见的时候被销毁了(调用了dealloc)

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

从错误可以得出的结论

  当popover仍旧可见的时候,不准销毁popover对象

  在销毁popover对象之前,一定先让popover消失(不可见)  

如:在上述代码中,如果不适用全局变量popover,那么将会出现上面的错误。

四、设置尺寸
提示:不建议,像下面这样吧popover的宽度和高度写死。
代码如下:

//1.新建一个内容控制器
    YYMenuViewController *menuVc=[[YYMenuViewController alloc]init];
   
    //2.新建一个popoverController,并设置其内容控制器
    self.popover=[[UIPopoverController alloc]initWithContentViewController:menuVc];
   
    //3.设置尺寸
    self.popover.popoverContentSize=CGSizeMake(300, 200);
   
    //4.显示
    [self.popover presentPopoverFromBarButtonItem:self.navigationItem.leftBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

更好的设计是:popover的尺寸应该由内部控制器的内容所决定。

内容控制器可以自行设置自己在popover中显示的尺寸,其中有两种方法:

(1)在iOS 7之前  @property (nonatomic,readwrite) CGSize contentSizeForViewInPopover;

(2)从iOS 7开始  @property (nonatomic) CGSize preferredContentSize;

  以上属性都是UIViewController的
代码如下:

-(NSArray *)menus
{
    if (_menus==nil) {
        _menus=@[@"列表1",@"列表2",@"列表3",@"列表4",@"列表4",@"列表4",@"列表4",@"列表4",@"列表4",@"列表4",@"列表1",@"列表2",@"列表1",@"列表2"];
    }
 return _menus;
}
- (void)viewDidLoad
{
    [super viewDidLoad];
   
    //设置控制器将来在popover中的尺寸
    CGFloat maxH=MIN(480,self.menus.count*44);
    //ios7以前的设置
//    self.contentSizeForViewInPopover=CGSizeMake(150, maxH);
    //ios7以后
    self.preferredContentSize=CGSizeMake(150, maxH);
   
}

效果:

关于MIN(A,B)的说明,最终的大小取决于B,但是最大不能超过A,如果超过A那么值就等于A。

五、设置显示的位置

1.设置显示的位置有2种方法

(1)围绕着一个UIBarButtonItem显示(箭头指定那个UIBarButtonItem)
代码如下:

- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated;

item :围绕着哪个UIBarButtonItem显示

arrowDirections :箭头的方向

animated :是否通过动画显示出来

(2)围绕着某一块特定区域显示(箭头指定那块特定区域)
代码如下:

- (void)presentPopoverFromRect:(CGRect)rect inView:(UIView *)view permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated;

rect :指定箭头所指区域的矩形框范围(位置和尺寸),以view的左上角为坐标原点

view :rect参数是以view的左上角为坐标原点(0,0)

arrowDirections :箭头的方向

animated :是否通过动画显示出来

rect和view参数如下:

相关代码:
代码如下:

//
//  YYViewController.m
//  01-PopoverController简单介绍
//
//  Created by apple on 14-8-17.
//  Copyright (c) 2014年 yangyong. All rights reserved.
//

#import "YYViewController.h"
#import "YYMenuViewController.h"

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

@interface YYViewController ()UIPopoverControllerDelegate
@property(nonatomic,strong)UIPopoverController *popover;
- (IBAction)buttonClick:(UIButton *)sender;
@end

代码如下:

@implementation YYViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
}

-(void)showPopoverFromItem
{
    //1.新建一个内容控制器
    YYMenuViewController *menuVc=[[YYMenuViewController alloc]init];
   
    //2.新建一个popoverController,并设置其内容控制器
    self.popover=[[UIPopoverController alloc]initWithContentViewController:menuVc];
   
    //3.设置尺寸
    //    self.popover.popoverContentSize=CGSizeMake(300, 200);
   
    //4.显示
    [self.popover presentPopoverFromBarButtonItem:self.navigationItem.leftBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
   
    //5.设置代理
    self.popover.delegate=self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   
}

#pragma mark-代理方法
//popoverController消失的时候调用
-(void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
}
//popoverController的位置改变的时候调用(如竖屏变横屏)
-(void)popoverController:(UIPopoverController *)popoverController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView *__autoreleasing *)view
{
   
}
//用来决定用户点击了蒙版后,popoverController是否可以dismiss,返回YES代表可以,返回NO代表不可以
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
    return NO;
}
- (IBAction)buttonClick:(UIButton *)sender {
   
    //1.新建一个popoverController并设置其内容控制器
    YYMenuViewController *menuVc=[[YYMenuViewController alloc]init];
    self.popover=[[UIPopoverController alloc]initWithContentViewController:menuVc];
   
    //2.显示
    //2.1第一种方式
//    [self.popover presentPopoverFromBarButtonItem:#(UIBarButtonItem *)# permittedArrowDirections:#(UIPopoverArrowDirection)# animated:#(BOOL)#];
    //2.2第二种方式
    [self.popover presentPopoverFromRect:sender.bounds inView:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    //说明:popover会指向sender.bounds这一块矩形框,这块矩形框以sender的左上角为坐标原点
    //注意:注意sender.frame和sender.bounds的区别
   
}
@end

界面效果:(部分)

关于frame坐标计算的图示:

下面两者是等价的:

即如果想让箭头指向某一个UIView的做法有2种做法,比如指向一个button

方法1
代码如下:

  [popover presentPopoverFromRect:button.bounds inView:button permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];

方法2
代码如下:

  [popover presentPopoverFromRect:button.frame inView:button.superview permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];

六、设置代理

代理对象
代码如下:

  @property (nonatomic, assign) id UIPopoverControllerDelegate delegate;

是否可见
代码如下:

  @property (nonatomic, readonly, getter=isPopoverVisible) BOOL popoverVisible;

箭头方向
代码如下:

  @property (nonatomic, readonly) UIPopoverArrowDirection popoverArrowDirection;

关闭popover(让popover消失)
代码如下:

  - (void)dismissPopoverAnimated:(BOOL)animated;

代码说明:
代码如下:

.......
  //5.设置代理
    self.popover.delegate=self;
}

#pragma mark-代理方法
//popoverController消失的时候调用
-(void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
}
//popoverController的位置改变的时候调用(如竖屏变横屏)
-(void)popoverController:(UIPopoverController *)popoverController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView *__autoreleasing *)view
{
   
}
//用来决定用户点击了蒙版后,popoverController是否可以dismiss,返回YES代表可以,返回NO代表不可以
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
    return NO;
}

七、防止点击UIPopoverController区域外消失

默认情况下

只要UIPopoverController显示在屏幕上,UIPopoverController背后的所有控件默认是不能跟用户进行正常交互的

点击UIPopoverController区域外的控件,UIPopoverController默认会消失

要想点击UIPopoverController区域外的控件时不让UIPopoverController消失,解决办法是设置passthroughViews属性
代码如下:

@property (nonatomic, copy) NSArray *passthroughViews;

这个属性是设置当UIPopoverController显示出来时,哪些控件可以继续跟用户进行正常交互。这样的话,点击区域外的控件就不会让UIPopoverController消失了

代码示例:
代码如下:

- (IBAction)buttonClick:(UIButton *)sender {
   
    //1.新建一个popoverController并设置其内容控制器
    YYMenuViewController *menuVc=[[YYMenuViewController alloc]init];
    self.popover=[[UIPopoverController alloc]initWithContentViewController:menuVc];
   
    //设置过滤掉一些控件
    self.popover.passthroughViews=@[self.switchview];
   
    //2.显示
    //2.1第一种方式
//    [self.popover presentPopoverFromBarButtonItem:#(UIBarButtonItem *)# permittedArrowDirections:#(UIPopoverArrowDirection)# animated:#(BOOL)#];
    //2.2第二种方式
//    [self.popover presentPopoverFromRect:sender.bounds inView:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    [self.popover presentPopoverFromRect:sender.frame inView:sender.superview permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    //说明:popover会指向sender.bounds这一块矩形框,这块矩形框以sender的左上角为坐标原点
    //注意:注意sender.frame和sender.bounds的区别
   
}

补充:

UIPopoverController这个类是只能用在iPad中的

要想在iPhone中实现popover效果,必须得自定义view,可以参考

展开更多 50%)
分享

猜你喜欢

iOS开发中UIPopoverController的使用详解

编程语言 网络编程
iOS开发中UIPopoverController的使用详解

详解iOS开发中Keychain的相关使用

编程语言 网络编程
详解iOS开发中Keychain的相关使用

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

iOS开发中UITabBarController的使用示例

编程语言 网络编程
iOS开发中UITabBarController的使用示例

详解iOS设计中的UIWindow使用

编程语言 网络编程
详解iOS设计中的UIWindow使用

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

iOS开发中CALayer使用的基本教程

编程语言 网络编程
iOS开发中CALayer使用的基本教程

iOS的UI开发中UITabBarControlle的基本使用教程

编程语言 网络编程
iOS的UI开发中UITabBarControlle的基本使用教程

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

强悍无比的WEB开发好助手FireBug(Firefox Plugin)

强悍无比的WEB开发好助手FireBug(Firefox Plugin)

快速制作USB版的Win7安装U盘

快速制作USB版的Win7安装U盘
下拉加载更多内容 ↓