【譯】理解iOS11中的WebView

(備注:本文由本人翻譯自Darryl PogueUnderstanding the WebView Viewport in iOS 11

下面為正文內(nèi)容:


理解iOS11中的WebView

發(fā)布于09/13/2017,作者:Darryl Pogue

iOS11在頂部狀態(tài)欄區(qū)域帶來了一些新的可能不太直觀的行為改變,但是這對那些使用如Apache Cordova或Ionic等工具的開發(fā)人員來說非常重要。值得說明的是,這種改變將會影響任何基于Web的使用了固定狀態(tài)欄的應用程序,當開發(fā)人員意圖為iOS11構(gòu)建這些應用程序時。那么此篇文章將會幫助您了解iOS11中的WebView組件。

注意:現(xiàn)有的應用程序依然將正常工作,因為其內(nèi)部的WebView的組件行為并未改變。這種改變只影響使用Xcode9編譯適配iOS11的應用程序。

為了理解這種變化,我們來看看歷史版本中狀態(tài)欄的變化。

狀態(tài)欄與安全區(qū)域

在早期版本的iOS中,狀態(tài)欄僅僅是屏幕頂部不變的不可觸控的黑色條。對開發(fā)人員來說狀態(tài)欄不過是一個系統(tǒng)UI,應用程序在它下面的空間運行而已。

這種情況隨著iOS7的到來有所變化,iOS7中的狀態(tài)欄變成了透明的,并根據(jù)導航欄(Navigation Bar)的顏色變化而變化。它意味著如Cordova這樣的WebView組件中的應用程序,必須檢測運行環(huán)境的iOS版本,并將20px的內(nèi)邊距固定添加到頁面的頂部,來保證下面內(nèi)容的顯示位置正確。

而在iOS7以后的版本中狀態(tài)欄只是增加了一些小的修正,包括增加了額外的橫幅在通話時或者后臺使用地理定位時。

對于本地應用來說,這部分是通過UINavigationBar和autolayout原生控件自動處理的。這些原生組件中的布局規(guī)則會保證內(nèi)容調(diào)整到適配狀態(tài)欄的正確高度,從而顯示在狀態(tài)欄不會遮擋它們的所謂“安全區(qū)域”中。同時,如果你的導航欄(UINavigationBar)靠部對其,它的顏色就會自動延伸到狀態(tài)欄后面,而形成統(tǒng)一的顏色。可不幸的是,對于基于Web的應用程序確不能享用這份福利。

iOS11中的改變

iPhone 8中iOS 11中的默認顯示。

iOS11中不同的是WebView中的內(nèi)容現(xiàn)在也增加了對這個所謂的“安全區(qū)域”的支持。它意味著當你的頁面中有個固定位置的標題欄元素(設置為top:0),那它在頁面渲染完成后會出現(xiàn)在屏幕頂部的20px以下也就是對齊了狀態(tài)欄的地方。但是,值得注意的是:當內(nèi)容向下滾動時,內(nèi)容會移動到狀態(tài)欄的后面;而內(nèi)容向上滾動時,將會再次跌落到狀態(tài)欄的下方。(留下一個很尷尬的差距落差效果,原文是個視頻,這里做了些截圖。)

頁面載入完成后
向上滾動
再向下滾動
最后

蘋果為什么要這樣設計?

我想你應該看過了PhoneX的設計,它有著不規(guī)則的屏幕形狀,在屏幕頂部切除了一塊區(qū)域用來放置揚聲器和相機。那么如果將頁面的元素固定到真實屏幕的頂部,將會出現(xiàn)部分內(nèi)容被放置在這塊切除區(qū)域中,而導致根本無法觸控使用。通過系統(tǒng)將它對齊到狀態(tài)欄的底部,可以確保頂部標題欄中的全部內(nèi)容都可以使用。

這很酷……除了現(xiàn)有的應用程序中出現(xiàn)的那20px的尷尬……

iOS11中的修正

幸運的是,蘋果為開發(fā)者提供了一種通過元標簽(head中的meta)來控制這個行為的方法。更幸運的是,蘋果甚至將這個修復補丁更新到了已經(jīng)被放棄的UIWebView控件中。

這個可設置的屬性是viewport-fit,它有三個可能的值:

  • contain:視圖窗口應包含全部網(wǎng)頁內(nèi)容,即內(nèi)容中的固定元素將被自動包含在所謂的“安全區(qū)域”中。
  • cover:網(wǎng)頁中需要處理全部視圖窗口即真實屏幕中的內(nèi)容,即你的頂部元素可能會被遮擋,你要自己處理就像在iOS10上面一樣。
  • auto:默認值,與contain相同

因此,你要想將你的標題欄還原到最頂部在狀態(tài)欄的后面,就像你在iOS10中做的,你要在你的頁面的head的meta中的viewport設置中增加viewport-fit=cover。

看起來很好的視口合適設置覆蓋在iOS 11在iPhone 8上。

iPhoneX

但是對于iPhoneX這種不規(guī)則的屏幕怎么辦呢?在iPhoneX上狀態(tài)欄不再是20像素高,并且因為揚聲器和相機的遮擋,你的標題欄將完全無法觸控使用了。需要注意的是,這種情況同樣會出現(xiàn)在固定在底部的頁腳部分,它將被麥克風遮擋住。

注意:如果你的應用程序中使用了Launch Storyboard方式,那你的應用程序就只能使用iPhoneX的全屏幕控件?,F(xiàn)有的應用程序?qū)⒆詣颖伙@示在頂部和底部之間的矩形空間中。(這個注意不是特別理解,感覺是啟動時用了Launch Storyboard,就是全屏幕顯示也就是WebView可以顯示全屏幕;以前編譯的應用會自動夾在中間區(qū)域,無法撐滿全屏)

iPhone X帶來了一些新的挑戰(zhàn),即使在窗口合適的情況下也可以覆蓋。

不過幸運的是,蘋果公司增加了一個方法,將這個“安全區(qū)域”的布局規(guī)范開放到了CSS中。它被作為一種常量設置被添加到了CSS中,可以通過CSS中的constant()函數(shù)來訪問,并且這個函數(shù)已經(jīng)被提交給了CSS工作組進行了標準化。

這4個常量分別為:

  • constant(safe-area-inset-top):獲取頂部安全區(qū)域插入值(單位為像素)
  • constant(safe-area-inset-bottom):獲取底部安全區(qū)域插入值(單位為像素)
  • constant(safe-area-inset-left):獲取左側(cè)安全區(qū)域插入值(單位為像素)
  • constant(safe-area-inset-right):獲取右側(cè)安全區(qū)域插入值(單位為像素)

而蘋果還給了我們一個禮物就是這個變量也被更新到了UIWebView中。

使用示例

假設你的頁面上有一個固定位置的標題欄,在iOS10中的設置是這樣的:

header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 44px;

    padding-top: 20px; /* 狀態(tài)欄高度 */
}

那么,要為iPhoneX或者其他iOS11的設備進行調(diào)整,你需要在頁面head中的viewport meta中增加:

<meta name="viewport" content=".... viewport-fit=cover">

更改CSS設置為:

header {
    /* ... */

    /* iOS10中狀態(tài)欄的高度 */
    padding-top: 20px;

    /* iOS11+中狀態(tài)欄的高度 */
    padding-top: constant(safe-area-inset-top);
}
iPhoneX中的自動填充

需要注意的是,對于不知道如何解析constant語法的舊設備來說,保留返回值是很重要的(我的理解就是指上面的padding-top:20px;)。另外,你還可以在CSS的calc()方法中使用這些常量。

如果你有底部導航欄的話,也要記得為它設置這個樣式內(nèi)容。


(這個是筆者的鳴謝,咱也替廣大開發(fā)者謝謝了?。?/p>

特此感謝蘋果公司的WebKit團隊的Timothy Horton研發(fā)了本文提到的viewport-fit和constant()功能。感謝Shazron,Julio,Kerri,Greg和Mike在測試和驗證中提供的貢獻。

(譯文完畢!)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容