iOS開發(fā)-Popover的使用

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)的視圖肛根。

截屏2019-12-28下午3.38.27.png

一般情況下,一個(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è)試一下

截屏2019-12-28下午4.29.52.png

發(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);
截屏2019-12-28下午4.53.52.png

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);

截屏2019-12-28下午5.05.01.png

那么模庐,如果我們想要將箭頭指向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);
截屏2019-12-28下午5.07.52.png

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);
截屏2019-12-28下午5.16.36.png

外觀屬性

另外還有一些控制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

UIPopoverController - UIKit | Apple Developer Documentation

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市饱搏,隨后出現(xiàn)的幾起案子非剃,更是在濱河造成了極大的恐慌,老刑警劉巖推沸,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件备绽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡坤学,警方通過查閱死者的電腦和手機(jī)疯坤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來深浮,“玉大人压怠,你說我怎么就攤上這事》晌” “怎么了菌瘫?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵蜗顽,是天一觀的道長。 經(jīng)常有香客問我雨让,道長雇盖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任栖忠,我火速辦了婚禮崔挖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘庵寞。我一直安慰自己狸相,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布捐川。 她就那樣靜靜地躺著脓鹃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪古沥。 梳的紋絲不亂的頭發(fā)上瘸右,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音岩齿,去河邊找鬼太颤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛纯衍,可吹牛的內(nèi)容都是我干的栋齿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼襟诸,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼瓦堵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起歌亲,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤菇用,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后陷揪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惋鸥,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年悍缠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了卦绣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡飞蚓,死狀恐怖滤港,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情趴拧,我是刑警寧澤溅漾,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布山叮,位于F島的核電站,受9級(jí)特大地震影響添履,放射性物質(zhì)發(fā)生泄漏屁倔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一暮胧、第九天 我趴在偏房一處隱蔽的房頂上張望锐借。 院中可真熱鬧,春花似錦叔壤、人聲如沸瞎饲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至妄田,卻和暖如春俺亮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疟呐。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國打工脚曾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人启具。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓本讥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鲁冯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拷沸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容