1. 背景
刘海屏指的是手机屏幕正上方由于追求极致边框而采用的一种手机解决方案。因形似刘海儿而得名。也有一些其他叫法:挖孔屏、凹口屏等,本文档统一按照刘海屏来命名。市场上已经有越来越多的手机都支持这种屏幕形式。
谷歌在安卓P版本中已经提供了统一的适配方案,可是在安卓O版本上如何适配呢?本文将详细介绍华为安卓O版本刘海屏适配方案。使用华为提供的刘海屏SDK进行适配,此方案也会继承到华为安卓P版本手机上。在华为P版本手机中将同时支持两种方案:华为O版本方案+谷歌P版本方案。另外因为安卓O版本的刘海屏手机已经在市场上大量上市,这些手机在市场上会存续2~3年。所以建议大家现在要同时适配华为O版本方案以及谷歌P版本方案。
一季度 | 二季度 | 三季度 | 四季度 | ||
安卓O (8.1) | P20/P20 Pro/Nova 3e/荣耀10等支持刘海屏 | 已发布手机继续存在市场 | 华为刘海屏适配方案 | ||
安卓P (9.0) | 新机 | 华为刘海屏适配方案和谷歌P版本适配方案并存 |
2. 华为已经发布的刘海屏手机信息
手机 | 分辨率 | dpi | 屏幕纵横比 | 屏幕纵横比 | 刘海高度 |
nova 3e | 1080*2280 | 480 | 19:9 | 2.11111 | 90 |
荣耀 10 | 1080*2280 | 480 | 19:9 | 2.11111 | 90 |
P20 | 1080*2244 | 480 | 18.7:9 | 2.0777777 | 85 |
P20 pro | 1080*2240 | 480 | 18.7:9 | 2.074074 | 81 |
3. 华为刘海屏手机安卓O版本适配方案
设计理念:尽量减少APP的开发工作量
处理逻辑:
4. 华为刘海屏API接口
4.1 判断是否刘海屏
4.1.1 接口描述
类文件 | 接口 | 接口说明 |
com.huawei.android.util.HwNotchSizeUtil | public static boolean hasNotchInScreen() | 是否是刘海屏手机: |
4.1.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; }}
4.2 获取刘海尺寸
4.2.1 接口描述
类文件 | 接口 | 接口说明 |
com.huawei.android.util.HwNotchSizeUtil | public static int[] getNotchSize() | 获取刘海尺寸:width、height int[0]值为刘海宽度 int[1]值为刘海高度。 |
4.2.2 调用范例
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; }}
4.3 应用页面设置使用刘海区显示
4.3.1 方案一
使用新增的Meta-data属性android.notch_support,在应用的AndroidManifest.xml中增加meta-data属性,此属性不仅可以针对Application生效,也可以对Activity配置生效。
1. 具体方式如下所示:
<meta-data android:name="android.notch_support" android:value="true"/>
2. 对Application生效,意味着该应用的所有页面,系统都不会做竖屏场景的特殊下移或者是横屏场景的右移特殊处理:
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:testOnly="false" android:supportsRtl="true" android:theme="@style/AppTheme"> <meta-data android:name="android.notch_support" android:value="true"/> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity>
3. 对Activity生效,意味着可以针对单个页面进行刘海屏适配,设置了该属性的Activity系统将不会做特殊处理:
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:testOnly="false" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name=".LandscapeFullScreenActivity" android:screenOrientation="sensor"> </activity> <activity android:name=".FullScreenActivity"> <meta-data android:name="android.notch_support" android:value="true"/> </activity>
4.3.2 方案二
使用给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"); }}
2. 接口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"); }}
3. 华为刘海屏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()); } }});
4. 使用和不使用刘海区效果对比:
设置使用刘海区效果图 不使用刘海区的效果图
设置使用刘海区效果图 不使用刘海区的效果图
4.4 获取默认和隐藏刘海区开关值接口
4.4.1 开关页面介绍
1. 老版本路径:“系统设置” > “显示” > “显示区域控制”。
2. 新版本路径:“系统设置” > “显示” > “屏幕顶部显示”
4.4.2 隐藏开关打开之后,显示规格
4.4.3 读取开关状态调用范例
public static final String DISPLAY_NOTCH_STATUS = "display_notch_status";int mIsNotchSwitchOpen = Settings.Secure.getInt(getContentResolver(),DISPLAY_NOTCH_STATUS, 0); // 0表示“默认”,1表示“隐藏显示区域”
温馨提示:文章内容系作者个人观点,不代表博观网对观点赞同或支持。
版权声明:本文为转载文章,来源于 华为官方文档 ,版权归原作者所有,欢迎分享本文,转载请保留出处!
发表评论