Android劉海屏適配

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章