Android 华为凹口屏基本了解

      Android8.0 以后【凹口屏】得到迅速发展,目前已有了挖孔屏/水滴屏/刘海屏等各式各样的屏幕,究其根本依旧是【凹口屏】,单华为一个品牌就涵盖了基本所有类型,而对于屏幕适配也是不可逃避的问题。小菜单独对华为各型号屏幕进行适配尝试,部分方法可通用到其他品牌设备,为 Android 标准 SDK 方法。

      其实凹口屏已经出现很久了,对于获取凹口宽高的方式也有很多种,但是以前主流的凹口屏中凹口位置一般是位于屏幕正上方,但随着发展,也出现了在左上角的挖孔屏样式。相应的,Android 9.0SDK28 也发布了获取凹口屏的方法。

Android 9.0 以下适配方案

      对华为设备凹口屏适配情况来说,若仅需获取凹口位置的宽高,如下方法即可,在 Android 各版本中均可(Android 9.0 及以上亦可)。此时获取屏幕水平方向安全位置时,可根据屏幕宽度-凹口宽度再左右均分即可。

/**
 * 华为凹口屏判断方法 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 及以上适配

      对于华为新出的挖孔屏设备基本均为 Android 9.0 及以上,Android 9.0 提供了对凹口屏相关的 SDK,谷歌认为凹口位置可以不固定位置也不固定个数,但是对于设备一条边只能有一个;如下方法对于 Android 9.0 及以上设备判断均可。SDK 不仅可以判断是否为凹口屏,同时可以获取各个凹口大小及所在位置。

步骤如下:
  1. 升级 build.gradlecompileSdkVersiontargetSdkVersion28
  2. ApplicationActivity 中设置 meta-data 属性,小菜测试不设置亦可;
<meta-data android:name="android.notch_support" android:value="true"/>
  1. 根据如下方法获取相应参数;
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);
    //设置页面全屏显示
    WindowManager.LayoutParams lp = getWindow().getAttributes();
    lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
    //设置页面延伸到凹口区显示
    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");//通过cutout是否为null判断是否凹口手机
                    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());//注意:凹口的数量可以是多个
                        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;
            }
        });
}

注意事项:

  1. 小菜在设置 ApplicationActivity 的主题为 NoActionBar 样式,此时要去掉 getSupportActionBar().hide(); 否则会报空指针异常;
<style name="NoBarTheme" parent="Theme.AppCompat.NoActionBar">
  <item name="android:windowNoTitle">true</item>
  <item name="android:windowContentOverlay">@null</item>
</style>
  1. 如下设置全屏使用凹口屏时要注意 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,否则参数很有可能获取不到;
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);
  1. 设置主题 NoActionBar 或代码中动态设置 getSupportActionBar().hide(); 展示效果在 Android 9.0 以下有部分差异,如下:
NoActionBar 主题
AppTheme 主题

      对于凹口屏适配还有很多机型要单独处理,以上仅对华为设备进行参考;如果有不对的地方还希望多多指出。

来源: 阿策小和尚

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容