由于刘海屏设备上市时运行的是 Android O 设备,而 Android O 没有标准接口来适配刘海屏设备,因此各大厂商针对Android O刘海屏适配方案也各有差异,具体如下:

华为刘海屏手机安卓O版本适配指导

小米刘海屏 Android O 适配

OPPO凹形屏适配说明

VIVO全面屏应用适配指南

后来 Android P 中新增了刘海屏适配的API,因此开发者需要针对 Android P 的设备重新适配,使用android标准接口来适配刘海屏设备,文档如下:

Android P 官方刘海屏适配规则及 API

Android P刘海屏适配规则(小米)


Android O 8.0刘海屏适配

  • 刘海屏幕机型在界面上的问题:

1.顶部内容会被刘海部分遮挡

2.如何处理耳朵区的显示区域

  • 系统如何适配?

1.status bar 的高度必须大于等于刘海的高度;对于应用来说,相当于一个更高的 status bar.

2.当应用显示 status bar 时(如微信首页),允许应用使用耳朵区(因为 status bar 区域本身不可交互,且会显示信号、电池等信息,因此我们假定应用不会在该区域放置重要的内容和可交互的控件)

3.当应用不显示 status bar 时(如全屏游戏),不允许应用使用耳朵区,系统默认填黑

4.横屏时,默认均不允许使用耳朵区,系统默认填黑

5.不允许应用180度倒转显示

  • APP如何适配?

1.检查设备是否为Notch设备

2.确定页面是否显示状态栏

3.尽量避免同一个APP不同页面显示和隐藏状态并存(会出现页面跳变的情况(应用的可用高度变了)

4.确定是否需要横屏显示Notch区域(若显示,需兼顾notch区域在左边/右边的情况)

5.检查是否写死了状态栏的高度值。Notch机器状态栏的值是变化的,建议改为读取系统的值

6.检查普通屏幕和刘海屏幕上的显示是否正常.


小米 Android O 刘海屏适配

  • 判断设备是否为刘海屏设备

系统增加了 property ro.miui.notch,值为1时则是 Notch 屏手机

SystemProperties.getInt("ro.miui.notch", 0) == 1;

调用示例:

public static int getInt(String key,Activity activity) {    int result = 0;    if (isXiaomi()){        try {            ClassLoader classLoader = activity.getClassLoader();            @SuppressWarnings("rawtypes")            Class SystemProperties = classLoader.loadClass("android.os.SystemProperties");            //参数类型            @SuppressWarnings("rawtypes")            Class[] paramTypes = new Class[2];            paramTypes[0] = String.class;            paramTypes[1] = int.class;            Method getInt = SystemProperties.getMethod("getInt", paramTypes);            //参数            Object[] params = new Object[2];            params[0] = new String(key);            params[1] = new Integer(0);            result = (Integer) getInt.invoke(SystemProperties, params);        } catch (Exception e) {            e.printStackTrace();        }    }    return result;}// 是否是小米手机public static boolean isXiaomi() {    return "Xiaomi".equals(Build.MANUFACTURER);}
  • 小米Application 级别的控制接口

其中,value 的取值可以是以下4种:

"none" 横竖屏都不绘制耳朵区(默认值,系统自动将应用页面下移挖孔高度的距离,保证应用布局显示在挖空区域以下)"portrait" 竖屏绘制到耳朵区"landscape" 横屏绘制到耳朵区"portrait|landscape" 横竖屏都绘制到耳朵区
  • Window 级别的控制接口

如果开发者希望对特定 Window 作处理,可以使用该接口。 在 WindowManager.LayoutParams 增加 extraFlags 成员变量,用以声明该 window 是否使用耳朵区。

其中,extraFlags 有以下变量:0x00000100 开启配置0x00000200 竖屏配置0x00000400 横屏配置

组合后表示 Window 的配置,如:

0x00000100 | 0x00000200 竖屏绘制到耳朵区0x00000100 | 0x00000400 横屏绘制到耳朵区0x00000100 | 0x00000200 | 0x00000400 横竖屏都绘制到耳朵区

控制 extraFlags 时注意只控制这几位,不要影响其他位。可以用 Window 的 addExtraFlags 和 clearExtraFlags 来修改, 这两个方法是 MIUI 增加的方法,需要反射调用。

int flag = 0x00000100 | 0x00000200 | 0x00000400;try {    Method method = Window.class.getMethod("addExtraFlags",            int.class);    method.invoke(getWindow(), flag);} catch (Exception e) {    Log.i(TAG, "addExtraFlags not found.");}

华为 Android O 刘海屏适配

  • 判断设备是否为刘海屏设备
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;    }}
  • 应用页面设置使用刘海区显示

使用新增的Meta-data属性android.notch_support,在应用的AndroidManifest.xml中增加meta-data属性,此属性不仅可以针对Application生效,也可以对Activity配置生效。

  • 使用给window添加新增的FLAG_NOTCH_SUPPORT
  1. 接口1描述:应用通过增加华为自定义的刘海屏flag,请求使用刘海区显示:
类文件 接口 接口说明
com.huawei.android.view.LayoutParamsEx public void addHwFlags(int hwFlags) 通过添加窗口FLAG的方式设置页面使用刘海区显示:public static final int FLAG_NOTCH_SUPPORT=0x00010000;

调用范例参考:

对Application生效,意味着该应用的所有页面,系统都不会做竖屏场景的特殊下移或者是横屏场景的右移特殊处理:

/*刘海屏全屏显示FLAG*/public static final int FLAG_NOTCH_SUPPORT=0x00010000;/** * 设置应用窗口在华为刘海屏手机使用刘海区 * @param window 应用页面window对象 */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");    }}
  1. 接口2描述:可以通过clearHwFlags接口清除添加的华为刘海屏Flag,恢复应用不使用刘海区显示。
类文件 接口 接口说明
com.huawei.android.view.LayoutParamsEx public void clearHwFlags (int hwFlags) 通过去除窗口FLAG的方式设置页面不使用刘海区显示:public static final int FLAG_NOTCH_SUPPORT=0x00010000;

调用范例参考:

/*刘海屏全屏显示FLAG*/public static final int FLAG_NOTCH_SUPPORT=0x00010000;/** * 设置应用窗口在华为刘海屏手机使用刘海区 * @param window 应用页面window对象 */public static void setNotFullScreenWindowLayoutInDisplayCutout (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("clearHwFlags", int.class);        method.invoke(layoutParamsExObj, FLAG_NOTCH_SUPPORT);    } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException |InstantiationException     | InvocationTargetException e) {        Log.e("test", "hw clear notch screen flag api error");    } catch (Exception e) {        Log.e("test", "other Exception");    }}
  1. 华为刘海屏flag动态添加和删除代码:
btn.setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(View view) {        if(isAdd) {//add flag            isAdd = false;            NotchSizeUtil.setFullScreenWindowLayoutInDisplayCutout(getWindow());                       getWindowManager().updateViewLayout(getWindow().getDecorView(),getWindow().getDecorView().getLayoutParams());        } else{//clear flag            isAdd = true;            NotchSizeUtil.setNotFullScreenWindowLayoutInDisplayCutout(getWindow());                        getWindowManager().updateViewLayout(getWindow().getDecorView(),getWindow().getDecorView().getLayoutParams());        }    }});

VIVO刘海屏判断

public static final int VIVO_NOTCH = 0x00000020;//是否有刘海public static final int VIVO_FILLET = 0x00000008;//是否有圆角public static boolean hasNotchAtVivo(Context context) {    boolean ret = false;    try {        ClassLoader classLoader = context.getClassLoader();        Class FtFeature = classLoader.loadClass("android.util.FtFeature");        Method method = FtFeature.getMethod("isFeatureSupport", int.class);        ret = (boolean) method.invoke(FtFeature, VIVO_NOTCH);    } catch (ClassNotFoundException e) {        LogUtil.e( "Vivo","hasNotchAtVivo ClassNotFoundException");    } catch (NoSuchMethodException e) {        LogUtil.e(  "Vivo","hasNotchAtVivo NoSuchMethodException");    } catch (Exception e) {        LogUtil.e(  "Vivo","hasNotchAtVivo Exception");    } finally {        return ret;    }}

OPPO刘海屏判断

public static boolean hasNotchAtOPPO(Context context) {     return  context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");}

更多相关文章

  1. Android核心分析(18)-----Android电话系统之RIL-Java
  2. 安卓JNI入门
  3. 【转】Android(安卓)JNI实例
  4. Android读书笔记-2 序列化
  5. 关于Android中aidl的关键词in,out,inout的探索
  6. Android(安卓)序列化
  7. android 播放器 实现场景搜索 调研
  8. Android(安卓)Binder 分析——匿名共享内存(Ashmem)
  9. Android下图形系统

随机推荐

  1. Linux_centos 搭建FTP服务器
  2. zabbix4.2-server安装 1
  3. Linux安装mysql数据库
  4. Linux 文件目录管理——创建
  5. Linux 文件目录管理——复制
  6. Grafana-server 6.2安装 1
  7. 美国人眼里的IaaS领导品牌调查(附原文)(20
  8. zabbix监控DELL iRADC风扇+温度+内存(zabb
  9. 最强监控---zabbix-server安装配置教程--
  10. Linux 下数据库定时备份