小米劉海屏適配方案

背景

1.目前已上市的小米 Notch 設備(俗稱劉海屏手機)如下,其寬度、高度和形狀均略有差異。

機型 model device 分辨率 Notch高度 Notch寬度 DPI
小米8 Xiaomi MI 8 dipper 1080*2248 89 560 440
小米8 SE Xiaomi MI 8 SE sirius 1080*2244 85 540 440
小米8 透明探索版 Xiaomi MI8 Explorer Edition ursa 1080*2248 89 560 440
紅米6 Pro Xiaomi Redmi 6 Pro sakura 1080*2280 89 352 440

注:以上設備,由於MIUI調整了DPI值,因此DP值與像素值的轉換關係是 1dp = 2.75 px 。

2..Android P 提供了 Notch / 劉海屏的標準適配接口

MIUI 也將在 Android P 上採用標準接口,因此,下文提及的接口僅用於 Android O 上。關於 Android P 的接口說明,詳見我的之前的文章:谷歌官方流海適配方案

系統級適配規則

Notch 機型在界面上會帶來兩個問題:

  1. 頂部內容會被 Notch 遮擋
  2. 如何處理耳朵區的顯示區域

爲了保證絕大部分應用都能正常顯示,同時儘可能利用屏幕的顯示區域。MIUI System UI 制定了以下全局規則:

  1. status bar 略高於 Notch 高度,對於應用來說,相當於一個更高的 status bar。
  2. 當應用顯示 status bar 時(如微信首頁),允許應用使用耳朵區(背後的邏輯是:因爲 status bar 區域本身不可交互,且會顯示信號、電池等信息,因此我們假定應用不會在該區域放置重要的內容和可交互的控件)。
  3. 當應用不顯示 status bar 時(如全屏遊戲),不允許應用使用耳朵區,系統默認填黑。
  4. 橫屏時,默認均不允許使用耳朵區,系統默認填黑。
  5. 不允許應用180度倒轉顯示。

開發者適配

系統規則只能解決最基礎的可用性問題,在系統規則下,開發者仍需要檢查以下內容:

  1. 檢查系統默認規則是否有可用性問題,考慮是否做針對性優化。
  2. 檢查 status bar 的顯示策略。重新考慮是否隱藏 status bar
  3. 儘量避免某些頁面顯示 status bar,某些頁面又隱藏,否則會出現頁面跳變的情況(應用的可用高度變了)。
  4. 檢查橫屏的情況,確定是否需要利用橫屏的Notch,若使用,需兼顧 Notch 出現在左邊/右邊的情況。
  5. 檢查是否寫死了狀態欄的高度值。Notch機器狀態欄的值是變化的,建議改爲讀取系統的值(後有相關方法說明)。
  6. 檢查開啓「隱藏屏幕劉海」後,應用是否顯示異常(詳見後文)。
  7. 檢查普通屏幕的顯示,保證應用在普通屏幕和 Notch 屏幕下都能正常顯示 。

系統接口說明

1.如何判斷設備爲 Notch 機型

SystemProperties.getInt("ro.miui.notch", 0) == 1;//系統增加了 property ro.miui.notch,值爲1時則是 Notch 屏手機。

2.如何獲取 Notch / 凹口 / 劉海 的高度和寬度(截至2018.6.26)

MIUI 10 新增了獲取劉海寬和高的方法,需升級至8.6.26開發版及以上版本。

以下是獲取當前設備劉海高度的方法:

int resourceId = context.getResources().getIdentifier("notch_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}

以下是獲取當前設備劉海寬度的方法:

int resourceId = context.getResources().getIdentifier("notch_width", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}

3.Application 級別的控制接口

如果開發者認爲應用的所有頁面統一處理就行,可以使用該接口。在 Application 下增加一個 meta-data,用以聲明該應用是否使用耳朵區。示例如下:

<meta-data
 android:name="notch.config"
 android:value="portrait|landscape"/>

其中,value 的取值可以是以下4種:

“none” 橫豎屏都不繪製耳朵區

“portrait” 豎屏繪製到耳朵區

“landscape” 橫屏繪製到耳朵區

“portrait|landscape” 橫豎屏都繪製到耳朵區

注:一旦開發者聲明瞭meta-data,系統就會優先遵從開發者的聲明。

4.Window 級別的控制接口

如果開發者希望對特定 Window 作處理,可以使用該接口。 在 WindowManager.LayoutParams 增加 extraFlags 成員變量,用以聲明該 window 是否使用耳朵區。

其中,extraFlags 有以下變量:

0x00000100 開啓配置

0x00000200 豎屏配置

0x00000400 橫屏配置

組合後表示 Window 的配置,如:

0x00000100 | 0x00000200 豎屏繪製到耳朵區

0x00000100 | 0x00000400 橫屏繪製到耳朵區

0x00000100 | 0x00000200 | 0x00000400 橫豎屏都繪製到耳朵區

控制 extraFlags 時注意只控制這幾位,不要影響其他位。可以用 Window 的 addExtraFlags 和 clearExtraFlags 來修改, 這兩個方法是 MIUI 增加的方法,需要反射調用。

int flag = 0x00000100 | 0x00000200 | 0x00000400;
try {
    Method method = Window.class.getMethod("addExtraFlags",
            int.class);
    method.invoke(getWindow(), flag);
} catch (Exception e) {
    Log.i(TAG, "addExtraFlags not found.");
}

5.狀態欄高度獲取方法

由於 Notch 設備的狀態欄高度與正常機器不一樣,因此在需要使用狀態欄高度時,不建議寫死一個值,而應該改爲讀取系統的值。

以下是獲取當前設備狀態欄高度的方法:

int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}

「隱藏屏幕劉海」適配

MIUI 針對 Notch 設備,有一個「隱藏屏幕劉海」的設置項(設置-全面屏-隱藏屏幕劉海),具體表現是:系統會強制蓋黑狀態欄(無視應用的Notch使用聲明),視覺上達到隱藏劉海的效果。但會給某些應用帶來適配問題(控件/內容遮擋或過於靠邊等)。

因此開發者在適配時,還需要檢查開啓「隱藏屏幕劉海」後,應用的頁面是否顯示正常。針對有問題的頁面,我們建議:

1.請通過以下方法獲取系統狀態欄高度,然後據此調整佈局,而不是寫死佈局:

int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
    result = context.getResources().getDimensionPixelSize(resourceId);
}

2.如有需要,可以通過查詢以下 Global settings 來確定「隱藏屏幕劉海」是否開啓了,然後再作針對性優化。

Settings.Global.getInt(mContext.getContentResolver(), "force_black", 0) == 1
發佈了44 篇原創文章 · 獲贊 8 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章