A popover is a transient view that appears above other content onscreen when you tap a control or in an area.
以上內(nèi)容來自蘋果官方人機(jī)交互指南中對(duì)Popover的簡介驰吓。
簡單來說Popover就是一個(gè)在正常操作流程中短暫出現(xiàn)的一個(gè)控制區(qū)域,一般會(huì)出現(xiàn)在iPad這類大屏設(shè)備中眯搭,并且包含一個(gè)指向的view和箭頭须教,比如官方文檔中給出的這個(gè)日歷中添加事項(xiàng)的視圖肛根。
一般情況下,一個(gè)Popover分為模態(tài)結(jié)構(gòu)(modal)和非模態(tài)結(jié)構(gòu)(nonmodal),在非模態(tài)結(jié)構(gòu)中基显,通常通過點(diǎn)擊其他區(qū)域來關(guān)閉Popover脱衙,
在模態(tài)結(jié)構(gòu)中侥猬,通過通過點(diǎn)擊頁面中的取消按鈕來關(guān)閉Popover。
在蘋果官方人機(jī)交互文檔中岂丘,蘋果建議使用Popover時(shí)遵循這些原則:
- 避免在iPhone上使用Popover
- 使用一個(gè)明確的關(guān)閉按鈕
- 在關(guān)閉時(shí)自動(dòng)保存Popover中的狀態(tài)
- 在屏幕中找到一個(gè)合適的位置彈出Popover
- 一次只顯示一個(gè)Popover
- 不要將Popover放的太大
更多遵循的原則和詳細(xì)的解析可以參看官方文檔對(duì)Popover的介紹陵究,鏈接在最下邊參考文檔中??????
接下來我們來看一下如何在iOS中使用Popover。
UIPopoverController
UIPopoverController是專為iPad設(shè)計(jì)的一個(gè)Controller奥帘,所以在iPhone中如果使用它會(huì)造成崩潰铜邮。
不過這個(gè)UIPopoverController在iOS9中被蘋果棄用了,取而代之的是UIPopoverPresentationController寨蹋,因?yàn)閁IPopoverPresentationController支持iOS8+松蒜,所以在這個(gè)iOS13的時(shí)代,我們就不多介紹UIPopoverController了已旧。
UIPopoverPresentationController
UIPopoverPresentationController基本上包括了之前說的UIPopoverController的特性秸苗,并且他也可以支持iPhone使用。
那么我們?nèi)绾蝸硎褂盟卦送剩O果官方文檔中有這樣一句話:
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 UIModalPresentationStyle.popover style. You can retrieve that instance from the presented view controller’s popoverPresentationController property and use it to configure the popover behavior.
也就是說惊楼,我們不需要直接創(chuàng)建UIPopoverPresentationController的實(shí)例玖瘸,當(dāng)我們創(chuàng)建一個(gè)present的Controller時(shí),使用Popover的樣式檀咙,系統(tǒng)就會(huì)自動(dòng)為我們創(chuàng)建一個(gè)實(shí)例雅倒,我們可以直接通過使用它的 popoverPresentationController屬性來對(duì)他進(jìn)行操作。
那么根據(jù)官方文檔弧可,我們通過簡單三行代碼蔑匣,就能創(chuàng)建出一個(gè)簡單的Popover了。
let popoverVC = PopoverViewController();
popoverVC.modalPresentationStyle = .popover;
self.present(popoverVC, animated: true, completion: nil);
然后愉快的在iPhone上測(cè)試一下
發(fā)現(xiàn)和正常的present好像沒什么區(qū)別棕诵,那看看iPad的上表現(xiàn)吧裁良,運(yùn)行起來之后,發(fā)現(xiàn)程序崩潰了校套,仔細(xì)看一下崩潰的信息
*** Terminating app due to uncaught exception ‘NSGenericException’, reason: ‘UIPopoverPresentationController (<UIPopoverPresentationController: 0x7ffe9c71fcc0>) should have a non-nil sourceView or barButtonItem set before the presentation occurs.’
***
原來是需要一個(gè)sourceView或者barButtonItem价脾,在iPad中使用過UIAlertController應(yīng)該對(duì)這個(gè)崩潰信息不陌生。那么除了要設(shè)置這個(gè)搔确,如果定制一個(gè)Popover我們還需要使用些什么呢彼棍?
因?yàn)檎麄€(gè)Popover基本上都是用于iPad的,并且蘋果官方也不太建議在iPhone上使用膳算,所以接下來的部分我們就不涉及在iPhone中使用Popover了座硕,所有的內(nèi)容都以iPad為標(biāo)準(zhǔn)介紹。
barButtonItem
這個(gè)屬性一般用于點(diǎn)擊導(dǎo)航欄的barButtonItem時(shí)顯示Popover涕蜂,他會(huì)自動(dòng)設(shè)置Popover的SourceView和SourceRect华匾,設(shè)定了之后,再在iPad上跑起來机隙,點(diǎn)擊導(dǎo)航欄上的Popover按鈕蜘拉,就可以看到,Popover已經(jīng)彈出來了有鹿。
let popoverVC = PopoverViewController();
popoverVC.modalPresentationStyle = .popover;
popoverVC.popoverPresentationController?.barButtonItem = self.barItem
self.present(popoverVC, animated: true, completion: nil);
sourceView 和 sourceRect
但是我們往往需求中旭旭,要求Popover不是指向于一個(gè)barButtonItem,而是我們自定義的一個(gè)view和位置葱跋,這時(shí)候就需要用到這兩個(gè)屬性了持寄。
sourceView為我們的Popover指向的view;
sourceRect為我們指向的基于sourceView的位置娱俺,默認(rèn)為CGRectZero稍味。
也就是說,默認(rèn)情況下荠卷,這段代碼的指向是這樣的(截圖中紅框?yàn)閎utton的frame):
let popoverVC = PopoverViewController();
popoverVC.modalPresentationStyle = .popover;
popoverVC.popoverPresentationController?.sourceView = self.popoverBtn;
popoverVC.popoverPresentationController?.sourceRect = CGRect.zero;
self.present(popoverVC, animated: true, completion: nil);
那么模庐,如果我們想要將箭頭指向button的下部中間位置,我們需要修改sourceRect
popoverVC.popoverPresentationController?.sourceRect = CGRect.init(x: self.popoverBtn.frame.size.width/2.0, y: self.popoverBtn.frame.size.height, width: 0, height: 0);
permittedArrowDirections
這個(gè)屬性表示的是允許的方向油宜,這個(gè)應(yīng)該很好理解掂碱,就不多做介紹了怜姿。
arrowDirection
這個(gè)屬性表示箭頭指向的方向,在彈出Popover之前顶吮,這個(gè)屬性為unknow社牲。
修改Popover的大小
在popoverPresentationController中,并沒有修改Popover的大小的屬性悴了,我們需要使用UIViewController中的preferredContentSize屬性來修改Popover的大小。
這樣一來违寿,定制一個(gè)Popover的基本操作就完成了湃交。
如下代碼就可以展示出一個(gè)這樣的Popover,當(dāng)然Popover中的具體內(nèi)容藤巢,可以直接在Popover的Controller中繪制搞莺。
let popoverVC = PopoverViewController();
popoverVC.modalPresentationStyle = .popover;
popoverVC.popoverPresentationController?.sourceView = self.popoverBtn;
popoverVC.popoverPresentationController?.sourceRect = CGRect.init(x: self.popoverBtn.frame.size.width/2.0, y: self.popoverBtn.frame.size.height, width: 0, height: 0);
popoverVC.popoverPresentationController?.permittedArrowDirections = .up;
popoverVC.preferredContentSize = CGSize.init(width: 100, height: 50);
self.present(popoverVC, animated: true, completion: nil);
外觀屬性
另外還有一些控制Popover外觀的屬性,比如:
- popoverLayoutMargins:定義Popover允許展示的區(qū)域之前的間隙
- backgroundColor:背景色
- passthroughViews:當(dāng)Popover顯示的時(shí)候掂咒,當(dāng)前Controller其他可以交互的view
- popoverBackgroundViewClass:自定義Popover的箭頭高度位置等等
- canOverlapSourceViewRect:Popover是否與sourceView重疊
等等才沧。這些屬性都很好理解,在使用的時(shí)候不明白的地方查查官方文檔就都很清楚了绍刮。
最后
以上就是在iOS中使用Popover的一些簡單介紹温圆,主要還是以UIPopoverPresentationController為主,當(dāng)然了還有一些其他的比如在iPad中使用UIAlertController時(shí)也會(huì)遇到這個(gè)問題孩革。但是基本上也都是一樣的東西岁歉,這里也就不多贅述了。
本文章僅限個(gè)人學(xué)習(xí)使用膝蜈,如果有什么問題歡迎大家批評(píng)指正锅移。
參考文檔
Popovers - Views - iOS - Human Interface Guidelines - Apple Developer
UIPopoverPresentationController - UIKit | Apple Developer Documentation