• Pad控件 UIPopoverController的介绍与使用(Pad的专属菜单控件、Swift版本)


    UIPopoverController 是iPad特有控件,iOS9之前,在iOS上也可以使用,在iOS9之后,只能用于Pad上。

    如果非要在iOS上使用,编译不会有问题,运行后会崩溃,报错如下:

    Terminating app due to uncaught exception 'NSInvalidArgumentException', 
    reason: '-[UIPopoverController initWithContentViewController:] called when not running under UIUserInterfaceIdiomPad.'

    因此,这里的介绍都是给予iPad来的,此文的Demo也得运行在Pad模拟器或pad真机上。

    --------------------------------------------------------------------- 

    如果想直接看最简单实现方式:

    点击这里查看

    ---------------------------------------------------------------------

    下面是具体讲解。

    1、关于UIPopoverController

    其实就是类似图中这样的菜单弹出框。

    在iOS上,我们可能要自己自定义或用三方封装好的菜单控件,但在pad上,我们可以直接使用系统提供的控件,简单快捷。

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

    1)设置内容控制器:
    由于UIPopoverController直接继承自NSObject,不具备可视化的能力,因此UIPopoverController上面的内容必须由另外一个继承自UIViewController的控制器来提供,这个控制器称为“内容控制器”
    
    2)设置内容的尺寸:
    显示出来占据多少屏幕空间
    
    3)设置显示的位置:
    从哪个地方冒出来

    这里有几点注意 :

    1、UIPopoverController不是一个view,不能直接显示或add到父view上,可以理解成一个盒子容器,盒子里面显示的内容需要一个额外的uiviewcontroller来呈现。

    2、设置大小,最好在盒子里面的控制器来设置,每个uiviewcontroller都有一个 preferredContentSize 属性来设置size。

    3、当然,如果想直接设置大小,也可以,不过如果内容控制器里设置了 preferredContentSize 大小 self.preferredContentSize = CGSizeMake(200, 200); 那么 self.popOver.popoverContentSize 将无意义。

    2、属性介绍

    设置内容的尺寸有2种方法:
    
    @property (nonatomic) CGSize popoverContentSize;
    
    - (void)setPopoverContentSize:(CGSize)size animated:(BOOL)animated;
    
    以上方法和属性都是UIPopoverController的

    如果通过内容控制器设置内容尺寸
    在iOS 7之前
    @property (nonatomic,readwrite) CGSize contentSizeForViewInPopover;
    
    从iOS 7开始
    @property (nonatomic) CGSize preferredContentSize;
    以上属性都是UIViewController的

    常用属性

    代理对象
    @property (nonatomic, assign) id <UIPopoverControllerDelegate> delegate;
    
    是否可见
    @property (nonatomic, readonly, getter=isPopoverVisible) BOOL popoverVisible;
    
    箭头方向
    @property (nonatomic, readonly) UIPopoverArrowDirection popoverArrowDirection;
    
    关闭popover(让popover消失)
    - (void)dismissPopoverAnimated:(BOOL)animated;

    设置显示的位置

    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的左上角为坐标原点(00)
    
    arrowDirections :箭头的方向
    
    animated :是否通过动画显示出来

    代理方法

    #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;
    }

    3、Demo代码介绍

    一个是显示控制器文件

    一个是popover的容器控制器文件

    显示控制器:

        var popOver:UIPopoverController!
        
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
            view.backgroundColor = UIColor.white
            
            self.navigationItem.title = "必须用pad模拟器或pad测试"
            
            let popVC = TestPopoverViewController()
            popVC.delegate = self       //代理为了点击内部的处理事件
            
            //添加contentview子视图,大小建议在子视图内部设置
            popOver = UIPopoverController(contentViewController: popVC)
            popOver.delegate = self
            
            //设置pop背景色,一般是为了和里面的content背景色一致,不然默认情况下会造成色差
            popOver.backgroundColor = UIColor.white
            
            //哪些控件可以继续跟用户进行正常交互。这样的话,点击区域外的控件就不会让UIPopoverController消失了
            //popOver.passthroughViews = [view]   //这句话加上后,点击蒙版,pop就不会消失,因为设置了view的交互可用
            
            //导航点击弹出
            self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(self.testNavPop))
            
            //按钮点击弹出
            testBtnPop()
            
        }

    这里我构造了两种弹出方式:

    1-导航栏位置   2-页面自定义位置,用一个按钮点击弹出

     

    1-导航栏位置弹出

     func testNavPop() {
            popOver.present(from: self.navigationItem.leftBarButtonItem!, permittedArrowDirections: .any, animated: true)
    
        }

    2-按钮位置弹出

    /// 在按钮弹出
        func btnClick(sender:UIButton) {
            //这种是紧靠着按钮位置弹出
            //popOver.present(from: sender.bounds, in: sender, permittedArrowDirections: .any, animated: true)
            
            //自定义弹出位置,比如这里我设置y上面与按钮间隔20
            popOver.present(from: CGRect(x: sender.bounds.origin.x, y: sender.bounds.origin.y+20,  sender.bounds.size.width, height: sender.bounds.size.height), in: sender, permittedArrowDirections: .any, animated: true)
            
        }

    代理事件:

    /// popover代理
    extension TestPadViewController:UIPopoverControllerDelegate{
        //popoverController消失的时候调用
        func popoverControllerDidDismissPopover(_ popoverController: UIPopoverController) {
            print("popoverControllerDidDismissPopover")
        }
        
        //popoverController的位置改变的时候调用(如竖屏变横屏)
        func popoverController(_ popoverController: UIPopoverController, willRepositionPopoverTo rect: UnsafeMutablePointer<CGRect>, in view: AutoreleasingUnsafeMutablePointer<UIView>) {
            print("willRepositionPopoverTo")
        }
        
        //用来决定用户点击了蒙版后,popoverController是否可以dismiss,返回YES代表可以,返回NO代表不可以
        func popoverControllerShouldDismissPopover(_ popoverController: UIPopoverController) -> Bool {
            return true
        }
    }
    
    /// popover容器内点击事件的代理
    extension TestPadViewController:TestPopoverViewControllerDelegate{
        internal func TestPopoverViewControllerDidSelect(index: NSInteger) {
            popOver.dismiss(animated: true)
            print("click (index)")
        }
    
        
    }

    容器控制器:

    var tableview:UITableView!
    
        var data = ["列表1","列表2","列表3","列表4","列表5","列表6","列表7","列表8"]
        
        weak var delegate:TestPopoverViewControllerDelegate?
        
    
        override func viewDidLoad() {
            super.viewDidLoad()
            view.backgroundColor = UIColor.white
            
            
            //设置pop框最大高度为150
            let maxH = min(150, 40*data.count)
            
            self.preferredContentSize = CGSize( 200, height: maxH)
            
            
            tableview = UITableView(frame: self.view.bounds, style: .plain)
            view.addSubview(tableview)
            tableview.dataSource = self
            tableview.delegate = self
            tableview.estimatedRowHeight = 40
            
        }

    用一个列表做示例。

    Demo下载,点击这里

    ~~

  • 相关阅读:
    Traceroute侦测主机到目的主机之间所经路由情况的重要工具
    TCP/IP详解之IP协议
    Hello world
    [LeetCode] 198. 打家劫舍
    [LeetCode] 191. 位1的个数
    [LeetCode] 190. 颠倒二进制位
    python里的排序
    [LeetCode] 189. 旋转数组
    [LeetCode]187. 重复的DNA序列
    [LeetCode] 179. 最大数
  • 原文地址:https://www.cnblogs.com/yajunLi/p/6639339.html
Copyright © 2020-2023  润新知