Android劉海屏適配問題(轉載)

Apple一直在引領設計的潮流,自從 iPhone X 發布之后,”劉海屏” 就一直存在爭議,本以為是一個美麗的錯誤(Bug),卻早就了一時間“劉海屏”的模仿潮。目前,國內已經推出的劉海屏”手機有 OPPO R15 和 華為 P20,并且Google也在IO大會上提高了相應的適配方案。

什么是劉海屏

屏幕的正上方居中位置(下圖黑色區域)會被挖掉一個孔,屏幕被挖掉的區域無法正常顯示內容,這種類型的屏幕就是劉海屏,也有其他叫法:挖孔屏、凹凸屏等等,這里統一按劉海屏命名。

就現在市場上的情況來說,“劉海屏”主要分成兩類,一類是標準的 Android P Api,另外一類就是廠商在 Android P 以下的系統,做的特殊適配。

例如:華為 P20 就是采用的 Android P 標準 Api 的方式,而 OPPO R15 就不一樣了,它有自己的適配 Api。

如何適配劉海屏

由于Android p正式版前兩天才發布, 當前市面上的Android 劉海屏手機還不能用Android 官方提供的方案來解決,那怎么辦呢?還好幾個廠商自己給出了適配方案(文末會接受使用Android P來適配劉海屏)。

華為P20

華為早在iPhone X發布后不久就推出了“劉海屏”P20,華為劉海屏適配官方文檔:

https://devcenter-test.huawei.com/consumer/cn/devservice/doc/50114

華為給出的文檔最為詳細適配文檔,P20 pro預裝系統對未做劉海屏適配處理的app有一定處理,處理的邏輯如下圖。

右上圖可知,華為系統做偏移處理的有以下2種情況:

1.未設置meta-data值,頁面橫屏狀態

2.未設置meta-data值,頁面豎屏狀態,不顯示狀態欄

適配劉海屏主要有以下幾個步驟:

1.配置meta-data

華為新增的Meta-data屬性android.notch_support在應用的AndroidManifest.xml中增加meta-data屬性,此屬性不僅可以針對Application生效,也可以對Activity配置生效,具體方式如下所示:

<meta-data android:name="android.notch_support" android:value="true"/>1

①對Application生效,意味著該應用的所有頁面,系統都不會做豎屏場景的特殊下移或者是橫屏場景的右移特殊處理:

② 對Activity生效,意味著可以針對單個頁面進行劉海屏適配,設置了該屬性的Activity系統將不會做特殊處理:

2.檢測是否存在劉海屏

public static boolean hasNotchInScreen(Context context) {

? boolean ret = false;

? try {

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

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

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

? ? ? ret = (boolean) get.invoke(HwNotchSizeUtil);

? } catch (ClassNotFoundException e) {

? ? ? Log.e("test", "hasNotchInScreen ClassNotFoundException");

? } catch (NoSuchMethodException e) {

? ? ? Log.e("test", "hasNotchInScreen NoSuchMethodException");

? } catch (Exception e) {

? ? ? Log.e("test", "hasNotchInScreen Exception");

? } finally {

? ? ? return ret;

? }

}1234567891011121314151617

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;

? }

}1234567891011121314151617

4. UI適配

通過增加上面適配方案提到的配置(meta-data或者是Flag),應用在華為劉海屏手機上就能夠默認使用劉海區顯示了,但是為了避免出現UI被劉海區遮擋的問題,還是需要應用自己做一些額外的UI適配工作:

(1)判斷是否劉海屏,通過華為劉海屏SDK的API判斷,具體參考3.2.1章節

(2)如果是劉海屏手機需要應用自己調整布局避開劉海區,布局原則:保證重要的文字、圖片和視頻信息、可點擊的控件和圖標還有應用彈窗等等布局建議顯示在狀態欄區域以下(安全區域);不重要,遮擋不會出現問題的布局可以延伸到狀態欄區域(危險區域)顯示,按照這種布局原則修改,可以一次修改就能適配所有的劉海屏手機:

獲取系統狀態欄高度接口:

public static int getStatusBarHeight(Context context) {

? ? int result = 0;

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

? ? if (resourceId > 0) {

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

? ? }

? ? return result;

}12345678

關于更詳細的適配資料,可以訪問華為劉海屏適配技術文檔。

vivo & OPPO

vivo 和 OPPO官網僅僅給出了適配指導,沒有給出具體方案,簡單總結為:

如有是具有劉海屏的手機,豎屏顯示狀態欄,橫屏不要在危險區顯示重要信息或者設置點擊事件。官方的文檔地址如下:

oppo官方文檔:

https://open.oppomobile.com/service/message/detail?id=61876

vivo官方文檔:

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

首先,判斷是不是劉海屏手機。

OPPO判斷方法:

public static boolean hasNotchInOppo(Context context){

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

}123

vivo的判斷方法:

public static final int NOTCH_IN_SCREEN_VOIO=0x00000020;//是否有凹槽

public static final int ROUNDED_IN_SCREEN_VOIO=0x00000008;//是否有圓角

public static boolean hasNotchInScreenAtVoio(Context context){

? boolean ret = false;

? try {

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

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

? ? ? Method get = FtFeature.getMethod("isFeatureSupport",int.class);

? ? ? ret = (boolean) get.invoke(FtFeature,NOTCH_IN_SCREEN_VOIO);

? } catch (ClassNotFoundException e)

? { Log.e("test", "hasNotchInScreen ClassNotFoundException"); }

? catch (NoSuchMethodException e)

? { Log.e("test", "hasNotchInScreen NoSuchMethodException"); }

? catch (Exception e)

? { Log.e("test", "hasNotchInScreen Exception"); }

? finally

? { return ret; }

}12345678910111213141516171819

然后在進行適配,官方這方面的資料很少也不是很詳細

google官方

google從Android P開始為劉海屏提供支持,目前提供了一個類和三種模式:

一個類指的是可以用DisplayCutout這個類找出劉海(cutout)的位置和形狀,調用getDisplayCutout()這個方法可以獲取劉海(cutout)的位置和區域。例如:

DisplayCutout cutout = mContext.getDisplayCutout();1

Google官方提供了三種模式,分別是:

LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT:僅僅當系統提供的bar完全包含了劉海區時才允許window擴展到劉海區,否則window不會和劉海區重疊

LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES:允許window擴展到劉海區(原文說的是短邊的劉海區, 目前有劉海的手機都在短邊,所以就不糾結了)

LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER:不允許window擴展到劉海區。

例如,下面是可以設置是否允許window擴展到劉海區的代碼。

WindowManager.LayoutParams lp =getWindow().getAttributes();?

lp.layoutInDisplayCutoutMode

=WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;?

getWindow().setAttributes(lp);1234

一個有狀態欄的頁面, 我們可以這樣適配:

DisplayCutout cutout = getDisplayCutout();

if(cutout != null){

WindowManager.LayoutParams lp =getWindow().getAttributes();?

lp.layoutInDisplayCutoutMode=WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;?

getWindow().setAttributes(lp);

}123456

當然如果你身邊還沒有劉海屏手機,可以使用Android P提供的模擬器,更新SDK到Android P preview版本。

然后,可以通過開發者選項里的 “Simulate a display with a cutout”,開啟劉海屏的支持,并且劉海屏有多個版本,需要注意它們的區別。

---------------------

作者:code_xzh

來源:CSDN

原文:https://blog.csdn.net/xiangzhihong8/article/details/80317682

版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,117評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,860評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,128評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,291評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,025評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,421評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,477評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,642評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,177評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,970評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,157評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,717評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,410評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,821評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,053評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,896評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,157評論 2 375

推薦閱讀更多精彩內容

  • 巜雨》 文:云煙 在綿綿的細雨里 攔截一個片段 化作秋思 潮潤一個季節 用母音呼喚流水的頓悟 在不一樣的花期里 看...
    當代詩人云煙閱讀 286評論 4 9
  • 今天內心平靜了很多,在感召學員的過程中還是有討好迎合的味道,也覺察到自己對于夸獎我的人完全沒有招架之力,所以我被夸...
    Hi_張閱讀 166評論 0 0
  • 愛情是一種被人高估了的情感,無論最后在不在一起,愛與被愛都是一種美好的體驗,同時,生活中還有很多其他有意思的事
    tao_162f閱讀 415評論 0 0