沉浸式,狀態欄高度,劉海屏怎麼開啓,適配

沉浸式,狀態欄高度,劉海屏怎麼開啓,怎麼適配?看這!
何爲沉浸式?

沉浸式就是app的頭部和狀態欄和何爲一體的,webview即爲整個手機的高度

何爲狀態欄?

狀態欄就是手機頂部,顯示時間電量那一行

除此還有劉海屏,水滴屏,挖孔屏,全面屏,非劉海屏,不同手機狀態欄高度又不太一樣,需要我們去適配,有一個段子說,如果看到那個手機適配有問題,趕緊把那個手機藏起來,不要讓測試發現了。

我們用HBuilder創建的應用默認是不開啓沉浸式的,需要我們手動如下配置開啓。

打開應用的manifest.json文件,切換到代碼視圖,在plus -> statusbar 下添加immersed節點並設置值爲true。

"plus": {
    "statusbar": {
        "immersed": true
    }
}

由於各系統版本的限制,沉浸式狀態欄對系統有要求(Android4.4及以上、iOS7.0及以上,這部分手機應該早已淘汰),如果要兼容各系統版本,需要動態判斷當前環境是否支持沉浸式狀態欄以及系統狀態欄的高度:

使用5+API

判斷當前環境是否支持沉浸式狀態欄
plus.navigator.isImmersedStatusbar()
如果當前支持沉浸式狀態欄則返回true,否則返回false。
獲取當前系統狀態欄高度
plus.navigator.getStatusbarHeight()
獲取系統狀態欄高度,Number類型。
其單位是邏輯像素值,即css中可直接使用的像素值,可能存在小數點
但是5+API需要在plusready事件後才能調用,通常此事件在DOM加載渲染後纔會觸發,無法再渲染前根據不同的狀態來設置css。所以會導致位置的一個閃動。

爲了解決此問題,在支持5+API運行環境的userAgent中特定字段Html5Plus/1.0後添加Immersed標識,如下:
“Html5Plus/1.0 (Immersed/30)”
其中Immersed/後的30表示狀態欄的高度,單位爲邏輯像素值。

可以使用正則表達式進行獲取:

var immersed = 0;  
var ms=(/Html5Plus\/.+\s\(.*(Immersed\/(\d+\.?\d*).*)\)/gi).exec(navigator.userAgent);  
if(ms&&ms.length>=3){ // 當前環境爲沉浸式狀態欄模式  
    immersed=parseFloat(ms[2]);// 獲取狀態欄的高度  
}

開啓了沉浸式,頁面就會往上移,頭部和狀態欄重合,所以我們設置界面頭區域的頂部內邊距爲狀態欄的高度

var t=document.getElementById(‘header’);
t&&t.style.paddingTop=immersed+‘px’;
不管是ios還是安卓,不管是劉海屏還是非劉海屏,都不用單獨去設置了,在公共js裏設置好頭部即可。

你學會了嗎?趕緊新建一個項目試試吧。

H5在全屏Webview中雙端適配劉海屏

這種的話一般是封裝一個Webview包含返回+標題+分享功能,然後加載H5即可,返回即關閉Webview,標題是讀取網頁的Title屬性,分享是調起客戶端的分享彈窗。

然是這次的H5有點不尋常的東西:

導航欄除了返回鍵、title、右側的操作菜單(進入另一個H5頁),在title還有一個操作項❔,用於點擊彈出說明框。
有一個穿透狀態欄和導航欄的背景

最終決定採用全屏Webview的形式,整個頁面交給H5控制,這樣不管頁面設計成什麼樣都能實現,什麼全屏背景,設麼導航啦加各種東西通通不在話下。於是愉快的開發開始了。

然鵝在打碼到一半的時候我意識到一個問題:雙端的狀態欄高度不一致,並且現在還有劉海屏存在🌚 這可腫麼辦?

一、IOS適配
首先對於IOS來說,喬幫主整的還是比較規範的,畢竟IOS閉源系統只能跑在Apple硬件上,設備型號有限,已知各機型尺寸如下:

注: 這裏獲取到的px值跟web中的px雖然單位一樣,但並不是我們需要的值!!!Web所需的px實際爲IOS中的pt值…,px轉pt需要根據設備的ppi(Pixels Per Inch: 像素密度)進行轉換:

px: pixel 像素,是屏幕上的顯示的基本點,他並不是長度單位,這個點可以很大,也可以很小。點小的話就很清晰,我們稱之爲“分辨率高”,反之就是“分辨率低”。所以像素是一個相對單位。

pt: point 準確的說法是一個專用印刷單位“鎊”,大小爲1/72英寸,是一個長度單位。也是絕對長度。

可以看到ios中的px轉pt根據設備的ppi大概是3:1/2:1/1:1轉換。
轉換完可以看到:

4.7寸6、6s、7、8,狀態欄高度爲20pt,導航欄高度爲44pt.
5.5寸的6p、6sp、7p、8p,狀態欄高度爲18pt,導航欄高度爲44pt.
擁有劉海屏的X、XR、XS、XS MAX、11等一系列劉海屏,狀態欄高度爲44pt,導航欄高度爲44pt.
不難發現:

導航欄 高度所有機型都爲44pt;
狀態欄 高度大致可以根據是否爲劉海屏分爲兩類。沒有劉海屏的大小機型分別爲18和20pt,可以近似的看成都是20pt來處理,問題不大,有劉海屏的則統一爲44pt高,跟導航欄高度相同。
適配方案:
iOS端的適配方案有兩種:Apple官方適配方案、機型區分適配、jsBridge方案

Apple官方適配方案:
1、在糞叉之後引入了一個新概念:“safe area(安全區域)”,安全區域指屏幕內不受圓角、齊劉海、底部小黑條等元素影響的可視窗口。如下圖:

2、同時,從iOS11開始,爲了適配劉海屏,Apple公司對HTML的viewport meta標籤做了擴展

viewport-fit=cover可設置爲auto, contain, cover三種狀態,這裏我們重點使用cover值,指頁面完全充滿屏幕。

3、iOS11同時新增了一個特性,constant(safe-area-inset-*),這是Webkit的一個CSS函數,用於獲取安全區域與邊界的距離,有四個預定義的變量(單位px):

safe-area-inset-left:安全區域距離左邊界距離,橫屏時適配
safe-area-inset-right:安全區域距離右邊界距離,橫屏時適配
safe-area-inset-top:安全區域距離頂部邊界距離,豎屏下劉海屏爲44px,iphone6系列20px,豎屏劉海適配關鍵
safe-area-inset-bottom:安全區域距離底部邊界距離,豎屏下爲34px,豎屏小黑條適配關鍵
這樣適配方案就比較明確了:

首先通過設置讓頁面充滿全屏
通過Webkit內置的CSS函數,獲取安全區域與各邊之間的間距,然後通過padding/margin/絕對定位等方式,讓頁面元素展示在安全區域內。
注: Webkit在iOS11中新增CSS Functions: env( )替代constant( ),文檔中推薦使用env( ),而 constant( ) 從Safari Techology Preview 41 和iOS11.2 Beta開始會被棄用。在不支持env( )的瀏覽器中,會自動忽略這一樣式規則,不影響網頁正常的渲染。爲了達到最大兼容目的,我們可以 constant( ) 和 env( ) 同時使用。

padding-top: constant(safe-area-inset-top); /* iOS 11.0 */
padding-top: env(safe-area-inset-top); /* iOS 11.2 */

最終適配代碼如下:

使用@supports查詢機型是否支持constant() / env()實現兼容代碼隔離,個別安卓也會成功進入這個判斷,因此加上-webkit-overflow-scrolling: touch的判斷可以有效規避安卓機。

@supports ((height: constant(safe-area-inset-top)) or (height: env(safe-area-inset-top))) and (-webkit-overflow-scrolling: touch) {
  .fullscreen {
    /* 適配齊劉海 */
    padding-top: 20;
    padding-top: constant(safe-area-inset-top);
    padding-top: env(safe-area-inset-top);
    
    /* 適配底部小黑條 */
    padding-bottom: 0;
    padding-bottom: costant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
  }
}

機型區分適配
這個就比較簡單粗暴無腦了。因爲目前市面上已有的Apple手機尺寸我們都是已知的,那剩下的就是css中的media適配了:

/* iphone x / xs / 11 pro*/
@media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) {
  ...
}
/* iphone xr / 11 */
@media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) {
  ...
}
/* iphone xs max / 11 pro max */
@media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) {
  ...
}

emmmmmm… 工作量大了點,另外每年9月份發佈會後要及時更新代碼🙈

jsBridge方案
如果你跟客戶端小哥哥的關係比較好的話,就用這種方案吧😳,讓客戶端寫個方法獲取狀態欄高度,然後在頁面加載的時候通過jsbridge調用獲取到狀態欄高度,然後設置頁面樣式即可。

好了,鄙人想到的iOS適配方案到此爲止。

二、Android適配方案
整完相對規範的iOS,開源的Android就相當眼花繚亂了,機器廠商百花齊放,各廠商的機型也是眼花繚亂。Android機型成百上千,適配方案反而變的簡單了!!!why? 因爲只有一種方案:JSBridge

像上述iOS的適配方案中,官方適配方案Android肯定是麼得了,畢竟機型太多,搞不了官方規範。其次就是CSS media 查詢精準適配,如果你的應用只針對於少數機型,那這種方案還是可以用用的,倘若不是那就拜拜了您嘞。

jsBridge方案
同iOS,客戶端獲取狀態欄高度後,H5通過JSBridge交互拿到狀態欄高度,設置頁面樣式避開齊劉海區域。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章