Android劉海屏適配
全屏模式下劉海屏黑邊(內容區域下挫)問題,支持國國內 華爲,小米,OPPO/VIVIO 非原生9.0系統的劉海屏
- 劉海屏是Android9.0之後才支持的 詳見源碼 android.view.DisplayCutout.class
- 國內主流手機也有劉海屏,官方有相關的劉海屏適配文檔,這裏提供一個工具類Util 可能更新不及時,僅供參考
- 最終效果是劉海屏不遮擋內容區域,支持旋轉,支持國內主流手機。如下
1. 設置全屏
Window window = getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
2. 設置沉浸式狀態欄
// 隱藏虛擬按鈕 可選 SYSTEM_UI_FLAG_HIDE_NAVIGATION
int flag = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
int visibility = window.getDecorView().getSystemUiVisibility();
visibility |= flag;
window.getDecorView().setSystemUiVisibility(visibility);
3. 讓內容延伸至劉海屏區域
3.1 判斷是否是劉海屏
注意,判斷方法需要放到獲取需要在view綁定到window之後,否則拿不到。建議在Activity.onAttachedToWindow()中處理
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
// 判斷是否有劉海區域
if(國內主流手機){
// Utils 工具類中有判斷是否是劉海屏,並設置全屏的處理辦法
}else{
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
Window window = getWindow();
DisplayCutout displayCutout = window.getDecorView().getRootWindowInsets().getDisplayCutout();
if(displayCutout != null){
// 有劉海屏
Log.e("displayCutout","Rect " + displayCutout.getBoundingRects());
Log.e("displayCutout","Rect " + displayCutout.getSafeInsetLeft());
Log.e("displayCutout","Rect " + displayCutout.getSafeInsetTop());
Log.e("displayCutout","Rect " + displayCutout.getSafeInsetRight());
Log.e("displayCutout","Rect " + displayCutout.getSafeInsetBottom());
// 3.2 讓內容延伸至劉海區域
// 3.3 劉海屏遮擋的區域下沉
}
}
}
}
3.2 讓內容延伸至劉海屏區域
/**
* public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT = 0; // 內容下移,非全屏模式不受影響
* public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES = 1; // 允許內容延伸進入劉海區域
* public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER = 2; // 不允許內容進入劉海屏區域
*/
WindowManager.LayoutParams layoutParams = window.getAttributes();
layoutParams.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
3.3 劉海屏遮擋的區域下挫/下沉
這裏有兩種方案,根容器設置padding or 修改劉海屏遮擋的空間的位置
- 根佈局設置padding 整體的內容區域下沉,此種情況,需要在根佈局設置background
// 整體的內容區域(根容器)下沉,將背景圖做爲根容器背景
findViewById(R.id.root_layout).setPadding(
displayCutout.getSafeInsetLeft(),
displayCutout.getSafeInsetTop(),
displayCutout.getSafeInsetRight(),
displayCutout.getSafeInsetBottom());
- 特定的控件設置padding or margin (設置距離頂部的距離)
View view = findViewById(R.id.cut_clickable_ll);
FrameLayout.LayoutParams cutLayoutParams = (FrameLayout.LayoutParams) view.getLayoutParams();
cutLayoutParams.topMargin = displayCutout.getSafeInsetTop();
view.setLayoutParams(cutLayoutParams);
小米vivo/oppo判斷劉海屏並適配工具類Utils