iPhoneX安全區(qū)域(Safe Area)底部小黑條在微信小程序和H5的屏幕適配

最近寫小程序時,遇到了 iPhoneX 底部小黑線與內(nèi)容重疊的問題奖磁,實際上是iPhoneX安全區(qū)域的適配問題定铜,了解清楚這個問題花了挺多時間的阳液,也實操出了結(jié)果,忍不住來總結(jié)總結(jié)揣炕。

本文目錄

前言
? ? ?? · 內(nèi)容與小黑線重疊情況說明
1.安全區(qū)域含義
2.微信小程序適配iPhoneX底部小黑條(Home Indicator)
? ? ?? (1)適配方案一:使用已知底部小黑條高度34px/68rpx來適配(不推薦)
? ? ?? (2)適配方案二:使用微信官方API帘皿,getSystemInfo()中的safeArea對象進(jìn)行適配(推薦)
? ? ?? (3)適配方案三:使用蘋果官方推出的css函數(shù)env()、constant()來適配 (推薦)
3.H5適配iPhoneX底部小黑條(Home Indicator)
? ? ?? · 適配方案:使用蘋果官方推出的css函數(shù)env()畸陡、constant()來適配 (推薦)

前言

在蘋果 iPhoneX 鹰溜、iPhone XR等設(shè)備上,可以看到物理Home鍵被取消丁恭,改為底部小黑條替代home鍵功能曹动。微信小程序和 h5 網(wǎng)頁需要針對這種情況進(jìn)行適配,否則可能會遇到底部按鈕或選項卡欄與底部黑線重疊的情況牲览,如下圖墓陈。

iPhoneX小黑條與按鈕重疊.jpg

1. 安全區(qū)域是什么意思?

想要解決內(nèi)容與小黑線重疊的問題第献,我們需要先了解清楚蘋果對于安全區(qū)域的定義贡必。

安全區(qū)域

安全區(qū)域指的是一個可視窗口范圍,處于安全區(qū)域的內(nèi)容不受圓角(corners)庸毫、齊劉海(sensor housing)仔拟、小黑條(Home Indicator)的影響。

看看蘋果官方給的這2張圖就明白了飒赃,中間藍(lán)色區(qū)域即為安全區(qū)域利花。也就是說科侈,適配安全區(qū)域也就是讓小程序或者H5的內(nèi)容顯示在藍(lán)色區(qū)域部分。

iphone-安全區(qū)域.png

同時安全區(qū)域是在IOS11之后并且是iPhoneX及以上機(jī)型才有的炒事,所以需要適配的是這一類機(jī)型(為了方便兑徘,下文中統(tǒng)稱這類需要適配的機(jī)型為iPhoneX),更老的機(jī)型則不需要考慮適配問題羡洛。

2. 在微信小程序上適配安全區(qū)域

三種方案:

  • 使用已知底部小黑條高度34px/68rpx來適配(不推薦)
  • 使用微信官方API挂脑,getSystemInfo()中的safeArea對象進(jìn)行適配(推薦)
  • 使用蘋果官方推出的css函數(shù)env()、constant()適配(推薦)

方案一:使用已知底部小黑條高度34px/68rpx來適配(不推薦)

這是比較老的方法欲侮,跟方案2崭闲、3比已經(jīng)不推薦了,大家可以了解了解威蕉,著急可以直接看方案2和3刁俭。

從網(wǎng)上了解到,iPhone底部的小黑條(Home Indicator)高度是34px韧涨,實際我也在真機(jī)確認(rèn)了是34px牍戚,所以可以根據(jù)該值,設(shè)置底部按鈕或選項卡的margin-bottom虑粥、padding-bottom如孝、height等,或者添加一個div來占位小黑條的位置娩贷。

這樣做要有一個前提第晰,需要判斷當(dāng)前機(jī)型是需要適配安全區(qū)域的機(jī)型。

問題:如何判斷當(dāng)前機(jī)型是需要適配安全區(qū)域

2種方案:

  • 使用wx.getSystemInfoSync()model屬性判斷
  • 使用wx.getSystemInfoSync()中的screenHeightsafeArea對象的bottom屬性判斷

方法一:使用wx.getSystemInfoSync()model屬性判斷

已知市面上已有的帶安全區(qū)域的蘋果設(shè)備包括iPhone X彬祖、iPhone XR茁瘦、iPhone XS Max、iPhone 11储笑、iPhone 11 Pro甜熔、iPhone 11 Pro Max,所以可以直接從getSystemInfoSync()方法中拿到model屬性進(jìn)行判斷突倍。iPhone系列微信還未適配手機(jī)的model返回值為unknown(iphone)腔稀,也可以提前做適配。

let IPHONE_X = /iphone x/i
let IPHONE_X_11 = /iphone 11/i
let IPHONE_UNKNOWN = /unknown\(iphone\)/i

//方法一:使用model判斷是否是IPhoneX及其他包含安全區(qū)域的機(jī)型手機(jī)
const isIPhoneX = () => {
  let model = wx.getSystemInfoSync().model
  return (model.search(IPHONE_X) > -1 || model.search(IPHONE_X_11) > -1 ||
    model.search(IPHONE_UNKNOWN) > -1)
}

//也可以使用正則表達(dá)式判斷
const isIPhoneXRegex = () => {
  let model = wx.getSystemInfoSync().model
  return (/iphone\sx/i.test(model)
    || (/iphone/i.test(model) && /unknown/.test(model))
    || /iphone\s11/i.test(model)) 
}

方法二:使用wx.getSystemInfoSync()中的screenHeightsafeArea對象的bottom屬性判斷

這里使用screenHeight而不是windowHeight赘方,因為bottom是以屏幕左上角為原點(diǎn)開始計算的烧颖,所以需要的是屏幕高度弱左,對比screenHeightbottom窄陡,如果相等則說明不需要適配,不相等則需要適配拆火。

注意:如果使用微信開發(fā)者工具中的模擬器跳夭,screenHeight和bottom始終是相等的涂圆,需要用真機(jī)來測試。

//方法二:使用wx.getSystemInfoSync()中的screenHeight和safeArea的bottom判斷
const isIPhoneX = () => {
  let screenHeight = wx.getSystemInfoSync().screenHeight
  let bottom = wx.getSystemInfoSync().safeArea.bottom
  return screenHeight !== bottom
}

解決了如何判斷設(shè)備是iPhoneX的問題币叹,就可以寫代碼了润歉。

<view class="bottom-button {{isIpX ? 'view-IPX' : ''}}">底部按鈕</view>

方案二:使用微信官方API,getSystemInfo()中的safeArea對象進(jìn)行適配(推薦)

使用wx. getSystemInfo()中的safeArea對象獲取底部小黑條的高度

step 1:使用上面講的方法先判斷是否是需要適配的iPhone機(jī)型
step 2:如果是需要適配的機(jī)型颈抚,使用safeArea中的bottom踩衩,得到安全區(qū)域底部縱坐標(biāo),然后使用screenHeight減去bottom就能得到小黑條的高度贩汉。保存到localstorage里面驱富,全局都可以使用。

iPhoneXSMAX-getSystemInfoSync獲得的對象.jpeg

方案三:使用蘋果官方推出適配方案css函數(shù)env()匹舞、constant()來適配 (推薦)

蘋果官方推薦使用env()褐鸥,constant()來適配,建議使用該方案赐稽,不需要管數(shù)值具體是多少叫榕。這2個方法是什么呢?

  • env()和constant()姊舵,是IOS11新增特性晰绎,Webkit的css函數(shù),用于設(shè)定安全區(qū)域與邊界的距離括丁,有4個預(yù)定義變量:
    • safe-area-inset-left:安全區(qū)域距離左邊邊界的距離
    • safe-area-inset-right:安全區(qū)域距離右邊邊界的距離
    • safe-area-inset-top:安全區(qū)域距離頂部邊界的距離
    • safe-area-inset-bottom :安全距離底部邊界的距離

因為目標(biāo)是需要對底部小黑條做適配寒匙,所以只需要關(guān)注safe-area-inset-bottom這個值。

而env()和constant()函數(shù)有個必要的使用前提躏将,當(dāng)網(wǎng)頁設(shè)置viewport-fit=cover的時候才生效锄弱,根據(jù)微信小程序的表現(xiàn)和我在實際真機(jī)測試時這兩個函數(shù)生效,推測小程序里的viewport-fit默認(rèn)是cover祸憋。

有一點(diǎn)要注意会宪,在IOS11.2系統(tǒng)以前,可以使用constant()函數(shù)蚯窥,但是在IOS11.2系統(tǒng)以后掸鹅,這個函數(shù)就被廢棄了,被env()函數(shù)替代了拦赠。官方原話如下:

The env() function shipped in iOS 11 with the name constant(). Beginning with Safari Technology Preview 41 and the iOS 11.2 beta, constant() has been removed and replaced with env(). You can use the CSS fallback mechanism to support both versions, if necessary, but should prefer env() going forward.

所以我們在做屏幕適配時巍沙,需要這樣寫:

padding-bottom: constant(safe-area-inset-bottom); /*兼容 IOS<11.2*/
padding-bottom: env(safe-area-inset-bottom); /*兼容 IOS>11.2*/

注意:env()和constant()需要同時存在,而且順序不能換荷鼠。

3. 在H5上適配安全區(qū)域

在H5上適配安全區(qū)域就方便多了句携,采用viewport+env+constant方案。

viewport-fit 默認(rèn)有3個值:

  • contain:可視窗口完全包含網(wǎng)頁內(nèi)容(左圖)
  • cover:網(wǎng)頁內(nèi)容完全覆蓋可視窗口(右圖)
  • auto:默認(rèn)值允乐,此值不影響初始布局視圖端口矮嫉,并且整個web頁面都是可查看的削咆。

contain和cover具體區(qū)別如下圖:

viewport屬性.png

而我們需要將viewport設(shè)置為cover,env和constant才能生效蠢笋。設(shè)置代碼如下:

<meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover">

同時設(shè)置env和constant代碼拨齐,同樣env()和constant()需要同時存在,而且順序不能換昨寞。

/* 可以通過增加padding-bottom來適配 */
padding-bottom: constant(safe-area-inset-bottom); /*兼容 IOS<11.2*/
padding-bottom: env(safe-area-inset-bottom); /*兼容 IOS>11.2*/

/* 可以通過margin-bottom來適配 */
margin-bottom: constant(safe-area-inset-bottom);
margin-bottom: env(safe-area-inset-bottom);

/* 或者改變高度*/
height: calc(55px +  constant(safe-area-inset-bottom));
height: calc(55px +  env(safe-area-inset-bottom));

也可以在底部添加一個空白的div顏色塊來做適配瞻惋。

還有一種是使用 @supports 隔離兼容樣式

可以使用 @supports 來隔離兼容樣式,當(dāng)瀏覽器支持bottom: constant(safe-area-inset-bottom)或者bottom: env(safe-area-inset-bottom)的時候援岩,bottom-button類就會新增margin-bottom的樣式

@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) { 
    .bottom-button {
        margin-bottom: constant(safe-area-inset-bottom);
        margin-bottom: env(safe-area-inset-bottom);  
    }
}

以上就是我對iPhoneX安全區(qū)域(Safe Area)底部小黑條在微信小程序和H5適配的總結(jié)熟史。

如果對你有幫助的話,點(diǎn)贊窄俏、評論蹂匹、贊賞都是對我的鼓勵,也是支持我寫下去的動力凹蜈,謝謝限寞!

參考文章:

本文原創(chuàng)發(fā)布于微信公眾號「程序員張晴天」仰坦,歡迎關(guān)注第一時間獲取最新分享履植,一起進(jìn)步。

微信公眾號-程序員張晴天.jpg
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末悄晃,一起剝皮案震驚了整個濱河市玫霎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌妈橄,老刑警劉巖庶近,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異眷蚓,居然都是意外死亡鼻种,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門沙热,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叉钥,“玉大人,你說我怎么就攤上這事篙贸⊥抖樱” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵爵川,是天一觀的道長敷鸦。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么轧膘? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任钞螟,我火速辦了婚禮兔甘,結(jié)果婚禮上谎碍,老公的妹妹穿的比我還像新娘。我一直安慰自己洞焙,他們只是感情好蟆淀,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著澡匪,像睡著了一般熔任。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上唁情,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天疑苔,我揣著相機(jī)與錄音,去河邊找鬼甸鸟。 笑死惦费,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的抢韭。 我是一名探鬼主播薪贫,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼刻恭!你這毒婦竟也來了瞧省?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤鳍贾,失蹤者是張志新(化名)和其女友劉穎鞍匾,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體骑科,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡候学,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了纵散。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梳码。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖伍掀,靈堂內(nèi)的尸體忽然破棺而出掰茶,到底是詐尸還是另有隱情,我是刑警寧澤蜜笤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布濒蒋,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏沪伙。R本人自食惡果不足惜瓮顽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望围橡。 院中可真熱鬧暖混,春花似錦、人聲如沸翁授。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽收擦。三九已至贮配,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間塞赂,已是汗流浹背泪勒。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宴猾,地道東北人圆存。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像鳍置,于是被迫代替她去往敵國和親辽剧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345

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