Android官方9.0刘海屏适配策略
- 如果非全屏(有状态栏),则app不受刘海屏的影响,刘海屏的高就是状态栏的高
- 如果全屏模式,app未适配刘海屏,系统会对界面做特殊处理,竖屏向下移动,横屏向右移动。
全屏情况下的适配,例:全屏展示图片
public class DisplayCutoutActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//1.设置全屏
requestWindowFeature(Window.FEATURE_NO_TITLE);
Window window = getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
//2.判断手机是否为刘海屏
boolean hasDisolayCutout = hasDisplayCutout(window);
if(hasDisolayCutout){
//3.让内容区域延伸进刘海
WindowManager.LayoutParams params = window.getAttributes();
/**
* 刘海屏三种展示模式
* LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 全屏模式下内容区下移,非全屏不受影响
* LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 允许内容区延伸进刘海区
* LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 不允许内容延伸进刘海区,无论是否为全屏模式
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
}
window.setAttributes(params);
//4.设置成沉浸式
int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
int visibility = window.getDecorView().getSystemUiVisibility();
visibility |= flags; //追加沉浸式设置
window.getDecorView().setSystemUiVisibility(visibility);
}
setContentView(R.layout.activity_immersive);
}
private boolean hasDisplayCutout(Window window){
DisplayCutout displayCutout;
View rootView = window.getDecorView();
WindowInsets insets = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
insets = rootView.getRootWindowInsets(); //窗口下挫
}
if(insets != null){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ) {
displayCutout = insets.getDisplayCutout();
if(displayCutout != null){
if(displayCutout.getBoundingRects() != null &&
displayCutout.getBoundingRects().size() > 0 &&
displayCutout.getSafeInsetTop() > 0){ //留海的高度
return true;
}
}
}
}
return false;
}
}
如果不是全屏展示图片,而是在顶部展示一个TextView或者Button之类的,可以通过getStatusBarHeight获取状态栏高度来对控件进行一个marginTop设置,因为通常情况下 状态栏的高度 >= 刘海的高度,所以以状态栏高度设置大概率不会出问题。
关于第三方ROM(华为 小米 oppo vivo)
- 判断手机厂商
- 判断手机是否有刘海
- 设置是否让内容区域延伸入刘海
- 设置控件是否避开刘海区域
- 获取刘海高度(displayCutout.getSafeInsetTop() 或 状态栏高度)