詳解Android 華為凹口屏適配小結(jié)
Android8.0以后【凹口屏】得到迅速發(fā)展,目前已有了挖孔屏/水滴屏/劉海屏等各式各樣的屏幕,究其根本依舊是【凹口屏】,單華為一個(gè)品牌就涵蓋了基本所有類(lèi)型,而對(duì)于屏幕適配也是不可逃避的問(wèn)題。小菜單獨(dú)對(duì)華為各型號(hào)屏幕進(jìn)行適配嘗試,部分方法可通用到其他品牌設(shè)備,為 Android 標(biāo)準(zhǔn) SDK 方法。
其實(shí)凹口屏已經(jīng)出現(xiàn)很久了,對(duì)于獲取凹口寬高的方式也有很多種,但是以前主流的凹口屏中凹口位置一般是位于屏幕正上方,但隨著發(fā)展,也出現(xiàn)了在左上角的挖孔屏樣式。相應(yīng)的, Android 9.0 即 SDK28 也發(fā)布了獲取凹口屏的方法。
Android 9.0 以下適配方案
對(duì)華為設(shè)備凹口屏適配情況來(lái)說(shuō),若僅需獲取凹口位置的寬高,如下方法即可,在 Android 各版本中均可( Android 9.0 及以上亦可)。此時(shí)獲取屏幕水平方向安全位置時(shí),可根據(jù)屏幕寬度-凹口寬度再左右均分即可。
/**
* 華為凹口屏判斷方法 Android 各版本均可
* @param context
* @return
*/
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(TAG, "hasNotchInScreen ClassNotFoundException");
} catch (NoSuchMethodException e) {
Log.e(TAG, "hasNotchInScreen NoSuchMethodException");
} catch (Exception e) {
Log.e(TAG, "hasNotchInScreen Exception");
} finally {
return ret;
}
}
/**
* 華為凹口屏寬高獲取方式 int[]{width, height}
* @param context
* @return
*/
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(TAG, "getNotchSize ClassNotFoundException");
} catch (NoSuchMethodException e) {
Log.e(TAG, "getNotchSize NoSuchMethodException");
} catch (Exception e) {
Log.e(TAG, "getNotchSize Exception");
} finally {
notchWidth = ret[0];
notchHeight = ret[1];
return ret;
}
}
Android 9.0 及以上適配
對(duì)于華為新出的挖孔屏設(shè)備基本均為 Android 9.0 及以上, Android 9.0 提供了對(duì)凹口屏相關(guān)的 SDK ,谷歌認(rèn)為凹口位置可以不固定位置也不固定個(gè)數(shù),但是對(duì)于設(shè)備一條邊只能有一個(gè);如下方法對(duì)于 Android 9.0 及以上設(shè)備判斷均可。 SDK 不僅可以判斷是否為凹口屏,同時(shí)可以獲取各個(gè)凹口大小及所在位置。
步驟如下: 升級(jí) build.gradle 中 compileSdkVersion 或 targetSdkVersion 為 28 ; 在 Application 或 Activity 中設(shè)置 meta-data 屬性,小菜測(cè)試不設(shè)置亦可;
<meta-data android:name="android.notch_support" android:value="true"/>
根據(jù)如下方法獲取相應(yīng)參數(shù);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
getSupportActionBar().hide();
getWindow().getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
//設(shè)置頁(yè)面全屏顯示
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
//設(shè)置頁(yè)面延伸到凹口區(qū)顯示
getWindow().setAttributes(lp);
getWindow().getDecorView()
.findViewById(android.R.id.content)
.getRootView()
.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
@Override
public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
DisplayCutout cutout = windowInsets.getDisplayCutout();
if (cutout == null) {
Log.e(TAG, "cutout==null, is not notch screen");//通過(guò)cutout是否為null判斷是否凹口手機(jī)
isNotchScreen = false;
} else {
List<Rect> rects = cutout.getBoundingRects();
if (rects == null || rects.size() == 0) {
Log.e(TAG, "rects==null || rects.size()==0, is not notch screen");
isNotchScreen = true;
} else {
Log.e(TAG, "rect size:" + rects.size());//注意:凹口的數(shù)量可以是多個(gè)
isNotchScreen = true;
for (Rect rect : rects) {
notchRight = rect.right;
notchLeft = rect.left;
notchTop = rect.top;
notchBottom = rect.bottom;
notchWidth = notchRight - notchLeft;
notchHeight = notchBottom - notchLeft;
safeLeft = cutout.getSafeInsetLeft();
safeRight = cutout.getSafeInsetRight();
safeTop = cutout.getSafeInsetTop();
safeBottom = cutout.getSafeInsetBottom();
}
}
}
return windowInsets;
}
});
}
注意事項(xiàng): 小菜在設(shè)置 Application 或 Activity 的主題為 NoActionBar 樣式,此時(shí)要去掉 getSupportActionBar().hide(); 否則會(huì)報(bào)空指針異常;
<style name="NoBarTheme" parent="Theme.AppCompat.NoActionBar"> <item name="android:windowNoTitle">true</item> <item name="android:windowContentOverlay">@null</item> </style>
如下設(shè)置全屏使用凹口屏?xí)r要注意 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN ,否則參數(shù)很有可能獲取不到;
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; getWindow().setAttributes(lp);
設(shè)置主題 NoActionBar 或代碼中動(dòng)態(tài)設(shè)置 getSupportActionBar().hide(); 展示效果在 Android 9.0 以下有部分差異,如下:

NoActionBar 主題

AppTheme 主題
對(duì)于凹口屏適配還有很多機(jī)型要單獨(dú)處理,以上僅對(duì)華為設(shè)備進(jìn)行參考;如果有不對(duì)的地方還希望多多指出。也希望大家多多支持腳本之家。
相關(guān)文章
解析Android中View轉(zhuǎn)換為Bitmap及getDrawingCache=null的解決方法
在android中經(jīng)常會(huì)遇到View轉(zhuǎn)換為Bitmap的情形,本篇文章主要介紹了Android中View轉(zhuǎn)換為Bitmap及getDrawingCache=null的解決方法,有需要的可以了解一下。2016-11-11
Unity同步/異步調(diào)用Android的方法實(shí)例
unity在Android端開(kāi)發(fā)的時(shí)候,免不了要調(diào)用Java,下面這篇文章主要給大家介紹了關(guān)于Unity同步/異步調(diào)用Android的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-08-08
Android5.0以上實(shí)現(xiàn)全透明的狀態(tài)欄方法(仿網(wǎng)易云界面)
下面小編就為大家分享一篇Android5.0以上實(shí)現(xiàn)全透明的狀態(tài)欄方法(仿網(wǎng)易云界面),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Android編程判斷SD卡是否存在及使用容量查詢(xún)實(shí)現(xiàn)方法
這篇文章主要介紹了Android編程判斷SD卡是否存在及使用容量查詢(xún)實(shí)現(xiàn)方法,實(shí)例分析了Android針對(duì)SD卡是否存在及使用容量、全部容量等的判斷技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-10-10
Android中ListView如何分頁(yè)加載數(shù)據(jù)
這篇文章主要介紹了Android中ListView如何分頁(yè)加載數(shù)據(jù),本文就結(jié)合實(shí)例來(lái)演示一下使用ListView獲取數(shù)據(jù)的過(guò)程,需要的朋友可以參考下2015-12-12
Android自定義有限制區(qū)域圖例角度自識(shí)別涂鴉工具類(lèi)中篇
這篇文章主要為大家介紹了Android自定義有限制區(qū)域圖例角度自識(shí)別涂鴉工具類(lèi)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
Android實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼倒計(jì)時(shí)功能示例
本篇文章主要介紹了Android實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼倒計(jì)時(shí)功能示例,這里整理了詳細(xì)的代碼,有需要的小伙伴可以參考下。2017-03-03
Android判斷App前臺(tái)運(yùn)行還是后臺(tái)運(yùn)行(運(yùn)行狀態(tài))
這篇文章主要介紹了Android判斷App前臺(tái)運(yùn)行還是后臺(tái)運(yùn)行的相關(guān)資料,需要的朋友可以參考下2016-04-04

