場景
app部分頁面使用H5混合開發,框架使用的是Vue。頁面基本在Android上展示正常,在ios(iPhone 7、iPhone X、iPhone 11)上會出現兩個問題:
(1) 頂部標題欄即便是fixed定位,top爲0,依然會留有一點縫隙,滑動的時候劉海左右兩邊可見滑動內容。
(2) H5頁面底部太貼近手機底部小黑條。
三種方案
根據問題場景,我想到了以下三個解決方案,並作了一一嘗試:
機型適配、佈局適配、app適配
方案對比
機型適配
方法1:屏幕尺寸適配
/* iphone x / xs / 11 pro*/
@media only screen and (device-width: 375px) and (device-height: 690px) and (-webkit-device-pixel-ratio: 3) {
header{
padding-top: 44px;
}
footer {
padding-bottom:34px;
}
}
/* 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) {
}
通過媒體查詢,指定尺寸的手機,上下留出一定邊距
這種方法比較笨,需要對出現問題的每款機型都做適配,而且需要知道對應機型的真實尺寸。不太推薦該方法,不過應該也是比較有效的方法。
然而嘗試發現,未解決問題。後來發現是頁面佈局本身原因導致未生效。
方法2:Safe Area適配
iPhone X之後,iphone上多了一個安全區域的概念,安全區域指的是一個可視窗口範圍,處於安全區域的內容不受圓角(corners)、齊劉海(sensor housing)、小黑條(Home Indicator)影響,如下圖綠色區域:
因此做好適配,必須保證頁面可視、可操作區域是在安全區域內。
適配第一步
<meta name="viewport" content="width=device-width,viewport-fit=cover">
viewport-fit特性主要有三個值可設
-
contain: 可視窗口完全包含網頁內容(左圖)
-
cover:網頁內容完全覆蓋可視窗口(右圖)
-
auto:默認值,跟 contain 表現一致
網頁默認不添加擴展的表現是 viewport-fit=contain,需要適配 iPhoneX 必須設置 viewport-fit=cover,這是適配的關鍵步驟。
適配第二步
body{
padding-top: env(safe-area-inset-top);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
padding-bottom: env(safe-area-inset-bottom);
}
對page頁面設置安全區域邊距。
constant() 以及 safe-area-inset-top safe-area-inset-right safe-area-inset-bottom safe-area-inset-left 是 iOS 11 webview 新增加的特性。
四個特性變量默認值如下:
safe-area-inset-top=0,
safe-area-inset-right=44px ,
safe-area-inset-bottom=21px,
safe-area-inset-left=44px
佈局適配
H5頁面大致可分爲三部分:頭部標題欄header,底部懸浮按鈕footer,中間內容區域。
原先的實現方法爲,header和footer都是fixed定位,中間默認爲static定位。
之所以在ios上出現上面的問題,從佈局上講,是劉海區域和底部區域爲可視區域。
那麼修改佈局也可實現。主要思路爲:
頁面滑動禁止,內容區域設置可滑動,即page的overflow設置爲hidden,內容區域設置爲scroll或auto。不過內容區域的高度設置應該在header和footer之間。
內容區域高度的計算方法,通過calc函數計算可得:
height:calc(100% - header高度 - footer高度);
依照思路,幾次調整佈局方式,頁面使用relative,header和footer嘗試過absolute定位實現,中間內容區域使用relative或fixed方式實現。
測試發現,確實這種方法在ios上可以實現適配。然而也帶來了其他問題。
Android端使用webview爲騰訊X5內核。適配後出現幾個問題:
1、滑動效果不太好 ,在ios上滑動還行,在Android反而有點滑動卡頓的問題。
2、頁面高度被壓縮,不能完全撐開,這個很致命!設置了固定高度後,如1000px,可以實現。然而內容區域高度本就是動態的,無法固定。
初步猜測,Android端webview頁頁包了一層body,而它的body高度是根據內容來的,並不是寬高默認全屏。
3、對於以上calc函數動態計算高度的問題不支持,不知道是不是版本的問題。
因此,該方案可行,卻會帶來新的兼容問題,需要對個別特性和方法做版本的適配支持。時間有限,最終沒有選擇該方案。
app適配
因爲H5頁面是內嵌在App內,所以換種思路,只需要將H5頁面限制在安全區域內即可,H5自己限定比較麻煩,可以交給app實現。對於ios來說,適配劉海屏反而相對簡單些,因爲不需要關心Android。
所以最終選擇的也是這個方案。ios根據機型辨別是否劉海屏,劉海頂部和靠近底部小黑條默認使用白色背景,將展示區域限制在safe Area中。