0
本文作者: 稀土 | 2016-08-05 09:21 |
雷鋒網(wǎng)按:本文由掘金翻譯計(jì)劃譯者llp0574譯自Douglas Hill《Preventing Popovers on Popovers》,校對(duì)者:yifili09、Graning。本文首發(fā)稀土掘金,未經(jīng)允許,禁止轉(zhuǎn)載。
iOS 9的頁(yè)面用了一種我們不能復(fù)現(xiàn)的方式去展示一個(gè)活動(dòng)視圖控制器,并且當(dāng)從內(nèi)部表單和彈窗呈現(xiàn)操作列表和活動(dòng)視圖控制器時(shí)UIKit的行為一開(kāi)始看起來(lái)不那么連貫。我們提交了兩份Radars給蘋(píng)果:Can't show activity view controller filling a form sheet 和 Reading an alert controller's popoverPresentationController property changes behavior.
不要在一個(gè)彈窗上展示一個(gè)模態(tài)視圖。 由于一個(gè)警告彈窗可能是一個(gè)異常,所以不應(yīng)該在這上面展現(xiàn)任何東西。極少數(shù)情況下,當(dāng)你真的需要在一個(gè)動(dòng)作導(dǎo)致彈窗后展示一個(gè)模態(tài)視圖時(shí),應(yīng)該先把彈窗關(guān)閉掉再進(jìn)行展示。
一次只展示一個(gè)彈窗。 展示多個(gè)彈窗會(huì)讓交互變得雜亂并讓人產(chǎn)生疑惑。千萬(wàn)不要展示一個(gè)級(jí)聯(lián)或者有層次結(jié)構(gòu)的彈窗,一個(gè)從另一個(gè)里面產(chǎn)生的那種。如果你需要展示一個(gè)新的彈窗,首先關(guān)閉已經(jīng)彈出的那個(gè)。
在橫向水平的普通環(huán)境和全屏緊湊的環(huán)境下具有彈窗樣式的視圖控制器都應(yīng)該呈現(xiàn)為彈窗。具有操作列表樣式的UIActivityViewController和UIAlertController都遵守相同的規(guī)則:展示為彈窗或者一個(gè)上拉式表。所以如果一個(gè)彈窗展示一個(gè)活動(dòng)視圖控制器或者一個(gè)操作列表到底會(huì)發(fā)生什么?這個(gè)人機(jī)交互指南文檔的說(shuō)法好像有點(diǎn)矛盾。
在iOS 9頁(yè)面的一個(gè)相關(guān)說(shuō)明里,我們注意到在一個(gè)表單的視圖控制器展示了一個(gè)填充了這個(gè)表單的UIActivityViewController,想知道這是不是一個(gè)我們之前沒(méi)有留意到的默認(rèn)行為呢?又或者它是不是一個(gè)我們可以自定義實(shí)現(xiàn)的東西?
對(duì)于大多數(shù)視圖控制器來(lái)說(shuō),在里面展示一個(gè)彈窗或者表單需要將當(dāng)前視圖控制器的modalPresentationStyle設(shè)置為currentContext或者overCurrentContext。但對(duì)于某些像UIActivityViewController和UIAlertController這種UIKit提供的視圖控制器來(lái)說(shuō),它們已經(jīng)被賦予了自己的樣式,modalPresentationStyle的變化將被忽略掉。
一般,UIActivityViewController會(huì)在常規(guī)寬度下展示為彈窗,在緊湊寬度下變成一個(gè)透明的表。但是如果一個(gè)常規(guī)寬度的視圖控制器要從一個(gè)緊湊寬度的視圖控制器里展示會(huì)怎么樣呢?這種情況會(huì)在一個(gè)有表格或者彈窗的modalPresentationStyle的視圖控制器要在iPad上展示,或者它是一個(gè)使用了overrideTraitCollection屬性的自定義展示控制器,然后這個(gè)控制器展示了一個(gè)UIActivityViewController。
首先我們來(lái)看看UIAlertController。圖中根視圖控制器(青色)用彈窗樣式(下方,通過(guò)切分視圖行為以作參考)展示了第二個(gè)用表單樣式(上方)的視圖控制器(粉色)。然后第二個(gè)視圖控制器展示了一個(gè)操作列表樣式的警告控制器。
雖然我們想要用列表的展示樣式去展示操作列表(而不是彈窗),但因?yàn)殛P(guān)注點(diǎn)分離的優(yōu)勢(shì),我設(shè)置了警告控制器的popoverPresentationController.sourceView和popoverPresentationController.sourceRect,視圖控制器不應(yīng)該對(duì)它怎么展示作出假設(shè)。它應(yīng)該在app的其他部分進(jìn)行全屏展示,視圖控制器不應(yīng)該控制這些行為。
出于好奇,我嘗試注釋掉了popoverPresentationController的定義,發(fā)生了讓我意想不到的情況:
原來(lái)只讀取警告控制器的popoverPresentationController屬性會(huì)導(dǎo)致即使是從一個(gè)緊湊寬度環(huán)境下呈現(xiàn)它也會(huì)展示為一個(gè)彈窗。如果你想這么做,請(qǐng)一定要確保好視圖控制器展現(xiàn)的前后環(huán)境,因?yàn)槿绻阆霃某R?guī)寬度的環(huán)境展現(xiàn)一個(gè)沒(méi)有設(shè)置彈窗源碼的警告控制器,UIKit就會(huì)拋出一個(gè)異常。切記在展現(xiàn)觸發(fā)的時(shí)候即使呈現(xiàn)視圖控制器是在一個(gè)緊湊寬度環(huán)境下,當(dāng)展示被激活的時(shí)候它還是有可能發(fā)生改變。
我提交了一個(gè)rdar:Reading an alert controller's popoverPresentationController property changes behavior.
用UIActivityViewController做同樣的事情,并指定彈窗源碼信息,出現(xiàn)下面的情況:
不同于頁(yè)面的行為,我發(fā)現(xiàn)表單把這個(gè)活動(dòng)視圖控制器展示為一個(gè)彈窗,彈窗將活動(dòng)視圖控制器展示在表單上。這是在iOS 10的新行為,iOS 9里,是從另一個(gè)彈窗展示一個(gè)彈窗。
用同樣不訪問(wèn)popoverPresentationController的技巧導(dǎo)致UIKit拋出一個(gè)異常說(shuō)“必須為這個(gè)彈窗提供位置信息”。
我們發(fā)現(xiàn)當(dāng)UIKit的視圖控制器是從一個(gè)展示在常規(guī)寬度環(huán)境的緊湊寬度的環(huán)境中展示時(shí)行為會(huì)變得很混亂。彈窗展現(xiàn)的一般規(guī)則是在常規(guī)寬度下展示為彈窗,在緊湊寬度下為全屏(盡管結(jié)合當(dāng)前上下環(huán)境更有意義)。操作列表和活動(dòng)視圖控制器的展示有點(diǎn)像彈窗的展示,但不要完全按照一般的規(guī)則來(lái)展示。
實(shí)際的行為看起來(lái)像是和人機(jī)交互指南說(shuō)的一樣,并很大程度上忽略了特征集合的Size類(lèi)。UIKit不會(huì)在操作列表的異常警告上展現(xiàn)一個(gè)彈窗。Size類(lèi)并不能控制所有的東西。
我們不能重現(xiàn)頁(yè)面(Pages)的行為。對(duì)于我們來(lái)說(shuō),當(dāng)一個(gè)表單展示一個(gè)活動(dòng)視圖控制器時(shí),它將展示為彈窗。我把這個(gè)問(wèn)題報(bào)告給了Apple(Radar:Can't show activity view controller filling a form sheet)。
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見(jiàn)轉(zhuǎn)載須知。