屏幕適配 | Android 劉海屏適配總結(jié)

一巨坊、簡介

隨著 Apple 發(fā)布 iPhone X 之后艇棕,各大手機廠商也開始模仿這種劉海屏的設(shè)計,而且劉海屏手機的用戶也是越來越大,前段時間將項目進行了所有主流廠商的劉海屏手機的適配矢渊,以便讓劉海屏手機的用戶也能有更好的體驗。

二枉证、劉海屏造成的 UI 顯示問題

劉海屏手機因為比平常的手機多了一塊頂部的遮擋性劉海矮男,所以會造成頂部 Toolbar 以及搜索框的遮擋,而且有些廠商的手機(vivo室谚、華為)毡鉴,默認是在「無狀態(tài)欄」的界面將狀態(tài)欄進行黑化顯示,這時候會導(dǎo)致系統(tǒng)下移秒赤,從而導(dǎo)致底部的一些 UI 被截斷猪瞬。除此之外,一些控件的顯示規(guī)則還會受到影響入篮,如 PopupWindow 的顯示高度會在「無狀態(tài)欄」的界面中比普通手機低一個「劉海的高度」陈瘦,從而遮擋住原先在 PopupWindow 周圍的圖標(biāo)。

1潮售、系統(tǒng)下移造成的底部 UI 截斷

小說頁碼被截斷

2痊项、劉海擋住標(biāo)題欄和搜索框

劉海擋住標(biāo)題欄和搜索框 ?

3、PopupWindow 顯示異常

PopupWindow 顯示異常 ?

三酥诽、通用的適配方案

理論上來講鞍泉,通過 Android P 版本提供的劉海屏相關(guān)接口,判斷手機是否為劉海屏手機肮帐,以及進行一些相應(yīng)的處理是最合適的方式咖驮,但現(xiàn)在使用在國內(nèi)使用 Android P 的接口是不現(xiàn)實的,所以只能通過各大廠商提供的技術(shù)文檔來進行適配训枢,但適配的流程基本是一致的游沿。

劉海屏的適配流程

其中需要著重處理的是:

????????1、應(yīng)用是否已經(jīng)適配劉海屏

????????2肮砾、頁面是否顯示狀態(tài)欄

3.1 應(yīng)用是否已經(jīng)適配劉海屏

現(xiàn)在國內(nèi)的主流機型(華為、vivo袋坑、OPPO仗处、小米)在劉海屏的顯示上分為兩個陣營:

? ? ? ? ?1、 當(dāng)不顯示狀態(tài)欄時枣宫,直接將界面進行顯示婆誓,「狀態(tài)欄原先的位置也用于顯示界面」,例如:OPPO

? ? ? ? ?2也颤、當(dāng)不顯示狀態(tài)欄時洋幻,直接「將狀態(tài)欄原先的位置進行黑化,界面整體下移」翅娶,例如:華為文留、vivo

所以好唯,我們在進行劉海屏適配的時候,首先需要通過一些手段燥翅,統(tǒng)一各大廠商的顯示方案骑篙,讓所有的劉海屏手機都利用狀態(tài)欄的界面,「告知系統(tǒng)」我們已經(jīng)適配了劉海屏森书,確保系統(tǒng)不會下移我們的應(yīng)用靶端,保留原生體驗。

這里主要有兩種方式:

1凛膏、設(shè)置屏幕高寬比例

因為劉海屏手機的「寬高比」比之前的手機大杨名,如果不適配的話,Android 默認為最大的寬高比為 1.86猖毫,

小于劉海屏手機的寬高比台谍,因此我們需要申明更高的寬高比來告訴系統(tǒng),我們應(yīng)用已經(jīng)適配了劉海屏鄙麦。

只要在 AndroidManifest.xml 中加入如下配置:

也可以在 Application 添加屬性:

android:maxAspectRatio="ratio_float"

ps:這個屬性需要 API 26 才支持

2典唇、設(shè)置應(yīng)用支持 resize

我們還可以通過設(shè)置應(yīng)用支持 resizeable,來告訴系統(tǒng)我們適配了劉海屏胯府,而且這也是 Google 官方推薦的方式介衔。不過需要注意的是,使用這個屬性之后骂因,應(yīng)用也會跟著支持分屏模式炎咖。只需要在 AndroidManifest.xml 中添加:

android:resizeableActivity="true"

3.2 頁面是否顯示狀態(tài)欄

對于劉海屏適配,我們將界面分為兩種:

????????對于有狀態(tài)欄的界面寒波,不會受到劉海屏的影響

????????全屏顯示的界面(無狀態(tài)欄)乘盼,需要根據(jù)界面的顯示進行一些控件的下移

因此,我們進行劉海屏適配俄烁,其實針對的就是沒有狀態(tài)欄的界面绸栅,而有狀態(tài)欄的界面顯示是正常的。對于沒有狀態(tài)欄的界面页屠,主要是將對被劉海遮擋到的控件粹胯,設(shè)置對應(yīng)劉海高度的 MarginTop,從而避免控件被遮擋辰企。而對于底部可能被截斷的界面风纠,可以考慮將底部做成 ScrollView 的形式。

四牢贸、各廠商的適配方案

現(xiàn)在 Android P 的接口還沒法用竹观,但各手機廠商都制定了自己的 API,對此我們需要對各大機型進行特殊的適配,這里主要介紹 vivo臭增、OPPO懂酱、華為 這三種主流手機的適配方案。

華為

華為作為國內(nèi)的手機廠商大頭速址,自己仿照 Android P 提供的 API玩焰,實現(xiàn)了一套幾乎差不多的 API,所以我們?nèi)绻胍嬖V系統(tǒng)我們的應(yīng)用適配了劉海屏芍锚,最好直接使用華為的 API昔园,這樣才是最保險的。

以下代碼來自:華為劉海屏適配官方技術(shù)指導(dǎo)

https://mini.eastday.com/bdmip/180411011257629.html

1并炮、應(yīng)用頁面設(shè)置使用劉海區(qū)顯示

① 方案一:在 AndroidManifest.xml 中增加 meta-data 屬性默刚,此屬性不僅可以針對 Application 生效,也可以對 Activity 配置生效:

增加這個屬性之后逃魄,系統(tǒng)就會對應(yīng)用進行下移處理荤西,從而保證原生體驗。

② 方案二:通過添加窗口 FLAG 的方式設(shè)置界面使用劉海區(qū):

public static void setFullScreenWindowLayoutInDisplayCutout(Window window) {? ?

????????if (window == null) {? ? ? ? return;? ? }? ?

????????WindowManager.LayoutParams layoutParams = window.getAttributes();? ?

????????try {? ? ? ?

????????????Class layoutParamsExCls = Class.forName("com.huawei.android.view.LayoutParamsEx");? ? ? ?

????????????Constructor con=layoutParamsExCls.getConstructor(LayoutParams.class);? ? ? ? ????????????Object layoutParamsExObj=con.newInstance(layoutParams);? ? ? ?

????????????Method method=layoutParamsExCls.getMethod("addHwFlags", int.class);? ? ? ? ????????????method.invoke(layoutParamsExObj, FLAG_NOTCH_SUPPORT);? ?

????} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException |InstantiationException? ? | InvocationTargetException e) {? ? ? ? Log.e("test", "hw add notch screen flag api error");? ? } catch (Exception e) {? ? ? ? Log.e("test", "other Exception");? ? }}

2伍俘、判斷該華為手機是否劉海屏

? ? public static boolean hasNotchInHuawei(Context context) {? ? ? ?

????????????boolean hasNotch = false;? ? ? ?

????????????try {? ? ? ? ? ?

????????????????????ClassLoader cl = context.getClassLoader();? ? ? ? ? ?

????????????????????Class HwNotchSizeUtil = ????????????????????cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? Method hasNotchInScreen =HwNotchSizeUtil.getMethod("hasNotchInScreen");? ? ? ? ? ?

????????????????if(hasNotchInScreen != null) {? ? ? ? ? ? ? ?

????????????????????????hasNotch = (boolean) hasNotchInScreen.invoke(HwNotchSizeUtil);? ? ? ? ?

? }? ? ? ? } catch (Exception e) {? ? ? ? ? ? e.printStackTrace();? ? ? ? }? ? ? ? return hasNotch;? ? }

3邪锌、獲取劉海的高度

? public static int[] getNotchSize(Context context) {? ? ?

????????????? int[] ret = new int[]{0, 0};? ? ? ?

????????????????try {? ? ? ? ? ?

????????????????????????ClassLoader cl = context.getClassLoader();? ? ? ? ? ?

????????????????????????Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");? ? ? ? ? ?

????????????????????????Method get = HwNotchSizeUtil.getMethod("getNotchSize");? ? ? ? ? ?

????????????????????????ret = (int[]) get.invoke(HwNotchSizeUtil); ? ? ? ?

} catch (ClassNotFoundException e) {? ? ? ? ? ? Log.e("test", "getNotchSize ClassNotFoundException");? ? ? ? } catch (NoSuchMethodException e) {? ? ? ? ? ? Log.e("test", "getNotchSize NoSuchMethodException");? ? ? ? } catch (Exception e) {? ? ? ? ? ? Log.e("test", "getNotchSize Exception");? ? ? ? } finally {? ? ? ? ? ? return ret;? ? ? ? }

OPPO

OPPO 是主流廠商中的一股清流,學(xué) iPhoneX 是最像的癌瘾,OPPO 手機對于不顯示狀態(tài)欄的界面觅丰,采取的是「狀態(tài)欄原先的位置也用于顯示界面」的方案,所以我們只要進行相關(guān)控件的位置移動就可以了妨退。

以下代碼來自: OPPO 凹形屏適配說明

https://open.oppomobile.com/wiki/doc#id=10159

1妇萄、判斷該 OPPO 手機是否為劉海屏手機

?? public static boolean hasNotchInOppo(Context context) {? ? ? ?

return context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");? ? }

2、獲取劉海屏的高度

對于 OPPO 劉海屏手機的劉海高度咬荷,OPPO 官方的文檔沒有提供相關(guān)的 API冠句,但官方文檔表示 OPPO 手機的劉海高度和狀態(tài)欄的高度是一致的,而且我也對此進行了驗證幸乒,確實如此懦底。所以我們可以直接獲取狀態(tài)欄的高度,作為 OPPO 手機的劉海高度罕扎。

public static int getStatusBarHeight(Context context) {? ?

????????int statusBarHeight = 0;? ?

????????int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");? ?

????????if (resourceId > 0) {? ? ? ?

????????????statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);? ?

????????}? ?

????????return statusBarHeight ;

}

vivo

vivo 提供的技術(shù)文檔對于開發(fā)者來說是最不友好的基茵,只提供了一個 API 來進行劉海屏的判斷,并沒有提供劉海高度的獲取方式壳影,我們只能通過獲取狀態(tài)欄高度來當(dāng)做劉海的高度,但在某些機型可能會有些偏差弥臼。

官方文檔:vivo 手機適配指南

https://dev.vivo.com.cn/doc/document/info?id=103

判斷該 vivo 手機是否為劉海屏手機

public static boolean hasNotchInVivo(Context context) {? ? ? ?

????????boolean hasNotch = false;? ? ? ?

????????try {? ? ? ? ? ?

????????????????ClassLoader cl = context.getClassLoader();? ? ? ? ? ?

????????????????Class ftFeature = cl.loadClass("android.util.FtFeature");? ? ? ? ? ?

????????????????Method[] methods = ftFeature.getDeclaredMethods();? ? ? ? ? ?

????????????????if (methods != null) {? ? ? ? ? ? ? ?

????????????????????????for (int i = 0; i < methods.length; i++) {? ? ? ? ? ? ? ? ? ?

????????????????????????????????Method method = methods[i];? ? ? ? ? ? ? ? ? ?

????????????????????????????????if(method != null) {? ? ? ? ? ? ? ? ? ? ? ?

????????????????????????????????????????if (method.getName().equalsIgnoreCase("isFeatureSupport")) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? hasNotch = (boolean) method.invoke(ftFeature, 0x00000020);? ? ? ? ? ? ? ? ? ? ? ? ? ?

????????????????????break;? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? } catch (Exception e) {? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? hasNotch = false;? ? ? ? }? ? ? ? return hasNotch;? ? }

五宴咧、總結(jié)

以上便是在之前在進行 Android 劉海屏適配的時候,所積累的一些經(jīng)驗和心得径缅。將其記錄下來掺栅,以便自己以后進行回顧烙肺,同時也希望這篇文章能對進行劉海屏適配的同學(xué)一些幫助。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末氧卧,一起剝皮案震驚了整個濱河市桃笙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沙绝,老刑警劉巖搏明,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異闪檬,居然都是意外死亡星著,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門粗悯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來虚循,“玉大人,你說我怎么就攤上這事样傍『岬蓿” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵衫哥,是天一觀的道長茎刚。 經(jīng)常有香客問我,道長炕檩,這世上最難降的妖魔是什么斗蒋? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮笛质,結(jié)果婚禮上泉沾,老公的妹妹穿的比我還像新娘。我一直安慰自己妇押,他們只是感情好跷究,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著敲霍,像睡著了一般俊马。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肩杈,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天柴我,我揣著相機與錄音,去河邊找鬼扩然。 笑死艘儒,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播界睁,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼觉增,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了翻斟?” 一聲冷哼從身側(cè)響起逾礁,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎访惜,沒想到半個月后嘹履,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡疾牲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年植捎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阳柔。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡焰枢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出舌剂,到底是詐尸還是另有隱情济锄,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布霍转,位于F島的核電站荐绝,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏避消。R本人自食惡果不足惜低滩,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望岩喷。 院中可真熱鬧恕沫,春花似錦、人聲如沸纱意。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽偷霉。三九已至迄委,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間类少,已是汗流浹背叙身。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留硫狞,地道東北人信轿。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓赞警,卻偏偏與公主長得像,于是被迫代替她去往敵國和親虏两。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

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