GitHub 中文社区iOS DeveloperiOS相关新技术

官方文档告诉你UIPopoverPresentationCont

2017-08-31  本文已影响1020人  love平_冲

何为UIPopoverPresentationController?
An object that manages the display of content in a popover.--一个用来管理在一个弹出窗口中展示内容的对象

先来看一下效果

使用UIPopoverPresentationController的效果

iOS9.0废弃的UIPopoverController

可以通过这篇文章了解一下以前的UIPopoverController使用方法UIPopoverController的使用

转到iOS8.0之后的UIPopoverPresentationController

官方文档对UIPopoverPresentationController的介绍原文为:

From the time a popover is presented until the time it is dismissed, UIKit uses an instance of this class to manage the presentation behavior. You use instances of this class as-is to configure aspects of the popover appearance and behavior for view controllers whose presentation style is set to popover
.

意思是说:从一个popover(也就是弹出的窗口)被presented(呈现)到被dismissed(退出)的期间,UIkit使用UIPopoverPresentationController的实例来管理呈现的行为。我们可以使用这个实例来为那些呈现的样式为popover的控制器设置popover的各个方面的外观和行为

另外官方文档还提到:

In nearly all cases, you use this class as-is and do not create instances of it directly. UIKit creates an instance of this class automatically when you present a view controller using the popover
style. You can retrieve that instance from the presented view controller’s popoverPresentationController
property and use it to configure the popover behavior.

意思是说:在几乎所有的情况下,我们都应该使用这个类并且不要直接创建它的实例。因为当我们present(呈现/弹出)一个控制器使用popover样式的时候,UIKit会自动为我们创建一个这个类的实例。我们可以通过控制器的popoverpresentationcontroller属性来重新获取UIPopoverPresentationController的实例,并且使用它来设置我们的popover的行为

如果当我们presenting一个控制器的时候,我们不想立即配置popover的话,我们可以使用它的代理去设置它。在present控制器的过程当中,UIPopoverPresentationController实例会调用遵守UIPopoverPresentationControllerDelegate的对象的很多方法,来询问一些信息和告诉它关于它应该呈现的状态

官方提供了如下的使用Swift代码的例子(我从Swfit切换到Objective-C,但还是显示的Swfit的例子😅,感觉苹果要默默干掉OC)

@IBAction func displayOptionsForSelectedItem () {
   let storyboard = UIStoryboard(name: "Main", bundle: nil)
   let optionsVC = storyboard.instantiateViewController(withIdentifier: "itemOptionsViewController")   
   optionsVC.modalPresentationStyle = .popover
   optionsVC.popoverPresentationController?.barButtonItem = optionsControl
   self.present(optionsVC, animated: true) {}
}

官方提供的示例代码就是简单的把设置了一下将要弹出的控制器的modalPresentationStyle和popoverPresentationController用来显示在什么位置。但是使用上述代码运行的话,我们会发现它竟然把要弹出的控制器全屏展示了(这可能不是我们想要的效果)

定制我们想要的popopver效果(介绍)

Customizing the Popover Behavior(定制popover的行为)
Configuring the Popover Appearance(设置popover的外观)
Specifying the Popover’s Anchor Point(指定popover的锚点)

锚点也就是popover的箭头所指向的位置

Configuring the Popover Arrows(设置popover的箭头)

UIPresentationController

UIPopoverPresentationController继承自UIPresentationController,这个对象的作用官方文档说是:一个为弹出的视图控制器提供高级视图和转场管理的对象。对于UIPresentationController更相近的内容限于篇幅,不再介绍,可以查看文档UIPresentationController

定制我们想要的popopver效果(实现)

先来说一下,如果我们像上文官方提供的例子的话,运行的结果将是全屏,这可能是系统会帮我们自适应弹出的样式,原因如下:

// By default this implementation defers to the delegate, if one exists, or returns the current presentation style. UIFormSheetPresentationController, and
// UIPopoverPresentationController override this implementation to return UIModalPresentationStyleFullscreen if the delegate does not provide an
// implementation for adaptivePresentationStyleForPresentationController:

open var adaptivePresentationStyle: UIModalPresentationStyle { get }

通过类型可以看出这个属性就是设置弹出popover的样式,再看一下注释,发现默认是根据UIAdaptivePresentationControllerDelegate实现的,如果实现了自适应样式的方法,那么这个属性的值就是设为响应的值。如果它的协议没有在adaptivePresentationStyleForPresentationController方法中实现的话,在UIFormSheetPresentationController和UIPopoverPresentationController重写了这个实现,并且返回UIModalPresentationStyleFullscreen。这就说明了,为什么官方的例子弹出的效果是全屏的了

UIAdaptivePresentationControllerDelegate

另外,我们注意到第二个方法的注释:返回UIModalPresentationNone指示不会发生自适应的样式,经过测试,果真如此。如果在这个代理方法返回UIModalPresentationNone,我们将可以定制我们自己的弹出样式,这也是本文所展示的效果的解决方法。同样,如果在第一个代理返回返回UIModalPresentationNone的话,也可以禁止弹出的自适应效果

了解了思路以后,用代码来写出我们想要的效果

效果图如下

基于父类是UIView的控件1

我们发现并不是我们想要的效果,popover的位置好像不对。调整它的位置,这时候就要用到sourceRect属性了。没有设置的情况下默认都是0,所以显示在了按钮的左上角(0,0,0,0)的位置,下面设置一下sourceRect属性

popoverPresentationController?.sourceRect = CGRect(x: btn.frame.size.width / 2, y: btn.frame.size.height, width: 0, height: 0)

效果图如下

基于父类是UIView的控件2

遗留问题:当第一次点击阴影使popover消失的时候,会报一个警告,可以点击这里进行了解

[Warning] <_UIPopoverBackgroundVisualEffectView 0x7f99f4607860> is being asked to animate its opacity. This will cause the effect to appear broken until opacity returns to 1.

参考文献:
UIPopoverPresentationController
UIPopoverController的使用

如果不想用系统的样式,也可以自定义,通过使用popoverBackgroundViewClass这个属性来自定义背景,具体可以参考这篇文章Customizing UIPopover with UIPopoverBackgroundView

上一篇 下一篇

猜你喜欢

热点阅读