谷歌官方流海适配方案
简介:
随着去年iPhone X的发布,今年android厂商也紧随其后,发布了各种异形屏手机(国内习惯称为刘海屏),作为Android的东家,google也是大力支持这种方案,然后就决定在系统级予以支持,所以从Android P开始,就提供了相应的接口,适配刘海屏,并且华为和小米已经明确说明了,以后的新系统会兼容google官方的解决方案,所以接下来,我就介绍一下官方的解决方案。
适配方案:
1.官方特性介绍
谷歌称刘海屏为凹口屏以及屏幕缺口支持, 下面的内容摘自:https://developer.android.com/preview/features#cutout
Android P 支持最新的全面屏以及为摄像头和扬声器预留空间的凹口屏幕。 通过全新的 DisplayCutout 类,可以确定非功能区域的位置和形状,这些区域不应显示内容。 要确定这些凹口屏幕区域是否存在及其位置,请使用 getDisplayCutout() 函数。
全新的窗口布局属性 layoutInDisplayCutoutMode 让您的应用可以为设备凹口屏幕周围的内容进行布局。 您可以将此属性设为下列值之一:
(1)LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
(2)LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
(3)LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
您可以按如下方法在任何运行 Android P 的设备或模拟器上模拟屏幕缺口:
(1)启用开发者选项。
(2)在 Developer options 屏幕中,向下滚动至 Drawing 部分并选择 Simulate a display with a cutout。
(3)选择凹口屏幕的大小。
注:我们建议您通过使用运行 Android P 的设备或模拟器测试凹口屏幕周围的内容显示。
2.相关接口介绍
(1)获取刘海尺寸相关接口:
https://developer.android.com/reference/android/view/DisplayCutout
方法 | 接口说明 |
---|---|
List getBoundingRects() | 返回Rects的列表,每个Rects都是显示屏上非功能区域的边界矩形。设备的每个短边最多只有一个非功能区域,而长边上则没有。 |
int getSafeInsetBottom() | 返回安全区域距离屏幕底部的距离,单位是px。 |
int getSafeInsetLeft () | 返回安全区域距离屏幕左边的距离,单位是px。 |
int getSafeInsetRight () | 返回安全区域距离屏幕右边的距离,单位是px。 |
int getSafeInsetTop () | 返回安全区域距离屏幕顶部的距离,单位是px。 |
(2)设置是否延伸到刘海区显示接口:
https://developer.android.com/reference/android/view/WindowManager.LayoutParams#layoutInDisplayCutoutMode
方法 | 接口说明 |
---|---|
int layoutInDisplayCutoutMode | 默认值: LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 其他可能取值: LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER |
https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
常量 | 常量说明 |
---|---|
int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT | 只有当DisplayCutout完全包含在系统状态栏中时,才允许窗口延伸到DisplayCutout区域显示。 |
int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER | 该窗口决不允许与DisplayCutout区域重叠。 |
int LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES | 该窗口始终允许延伸到屏幕短边上的DisplayCutout区域。 |
3.代码实现
(1)设置使用刘海区显示代码:
//使内容出现在status bar后边,如果要使用全屏的话再加上View.SYSTEM_UI_FLAG_FULLSCREENgetWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | 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);
(2)获取刘海屏安全显示区域和刘海尺寸信息:
getWindow().getDecorView().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判断是否刘海屏手机 } else { List rects = cutout.getBoundingRects(); if (rects == null || rects.size() == 0) { Log.e(TAG, "rects==null || rects.size()==0, is not notch screen"); } else { Log.e(TAG, "rect size:" + rects.size());//注意:刘海的数量可以是多个 for (Rect rect : rects) { Log.e(TAG, "cutout.getSafeInsetTop():" + cutout.getSafeInsetTop() + ", cutout.getSafeInsetBottom():" + cutout.getSafeInsetBottom() + ", cutout.getSafeInsetLeft():" + cutout.getSafeInsetLeft() + ", cutout.getSafeInsetRight():" + cutout.getSafeInsetRight() + ", cutout.rects:" + rect ); } } } return windowInsets; }});
UI适配
1.判断是否为刘海屏
见上边代码
2.调整布局
如果是刘海屏,调整布局避开刘海区。
布局原则:保证重要的文字、图片、视频信息、可点击的控件和图标,应用弹窗等,建议显示在状态栏区域以下(安全区域)。如果内容不重要或者不会遮挡,布局可以延伸到状态栏区域(危险区域)。
建议按照如下布局原则修改:
3.获取状态栏高度
经过试验研究,小米和华为的获取的高度就是刘海的高度,并且在不同状态下这个值会有所变化
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;}
更多相关文章
- 目前 Android平板所面临的几个问题
- 在Android里如何判断一个指定的经纬度点是否落在一个多边形区域
- Android(安卓)6.0新特性之WebView不能适配屏幕解决方案
- 一些关于android屏幕的小知识
- UI效果(9): 屏幕相关操作
- HTC Desire HD (G10)初体验
- Android(安卓)UI 之 各种长度单位
- Android重力感应基础
- [UI控件问题] android屏幕自适应 android 属性