一、什么时候需要适配刘海屏?
全屏模式,并且手机有刘海,则需要适配刘海屏。
非全屏模式(有状态栏),则刘海屏的高度为状态栏高度,不需要适配。
如果全屏模式,没有适配刘海屏,则系统会做特殊处理,界面在竖屏时,会向下移动,横屏时,向右移动。
二、如何适配刘海屏
1.全屏模式-内容延伸到刘海
// 需要在setContentView 之前执行
// 隐藏标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE)
// Window设置全屏
Window window = getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManger.LayoutParams.FLAG_FULLSCREEN)
// 设置全屏模式后,如果没有做适配,则内容自动向下移动,避开挖孔区域
// 判断手机是否是刘海屏
DisplayCutout displayCutout = false;
View rootView = window.getDecorView();
WindowInsets insets = rootView.getRootWindowInsets();
if (insets != null) {
displayCutout = insets.getDisplayCutout();
if (displayCutout != null) {
if (displayCutout.getBoundingRects() != null && displayCutout.getBoundingRects().size() > 0 && dispalyCutout.getSafeInsetTop() > 0)
displayCutout = true;
}
}
// 如果想让内容延伸到刘海区域,则需要设置 WindowManager.LayoutParams layoutInDisplayCutoutMode
WindowManager.LayoutParams params = window.getAttributes();
// layoutInDisplayCutoutMode 有三个值
// LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT: 默认模式,全屏模式,内容下移,非全屏模式,不受影响
// LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES :允许内容区延伸至刘海区(根view延伸)
// LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_NEVER 不容许内容延伸到刘海区,非全屏模式,也看不到刘海区
params.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES ;
window.setAttributes(params);
2.设置沉浸式-内容延伸到状态栏
// layoutInDisplayCutoutMode 设置为LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 后,只是根view延伸到刘海区,我们设置的布局并不会延伸到刘海区,需要设置沉浸式
// 设置沉浸式 Activity全屏显示覆盖状态栏|隐藏导航栏|Activity全屏显示,但是显示状态栏,activity顶端布局被覆盖
int flags = View.SYSTEM_UI_FLAG_FULLSCREEN // Activity全屏显示覆盖状态栏
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // 导航栏不会被隐藏但activity布局会扩展到导航栏所在位置
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // 状态栏不会被隐藏但activity布局会扩展到状态栏所在位置 ;
// 获取decorview的SysteUiVisibility
int visibility = window.getDecorView().getSysteUiVisibility();
visibility |= flags;
window.getDecorView.setSystemUiVisibility(visibility);
3.如何避开刘海区域
// 对不应该改进入刘海区域的view处理方式, 可以通过设置margin或者父容器的padding进行处理
// 获取状态栏高度,通常情况下刘海的高度等于状态栏的高度,也可以通过DisplayCutout 获取
int statusbarHeight;
int resID = getResources().getIdentifer("status_bar_height", "dimen", "android");
if (resID > 0) {
statusbarHeight = getResoureces().getDimensionPixelSize(resID);
}
// 设置padding
Button button = findViewById(R.id.button);
RelativeLayout.LayoutParams layoutparams = (RelativeLayout.LayoutParams) button.getLayoutParams();
layoutparams.topMargin = statusbarHeight;
button.setLayoutParams(laoutParams);
4.各厂商对刘海屏的适配
华为:https://developer.huawei.com/consumer/cn/devservice/doc/50114
小米:https://dev.mi.com/console/doc/detail?pId=1293
Oppo:https://open.oppomobile.com/service/message/detail?id=61876
Vivo:https://dev.vivo.com.cn/documentCenter/doc/103