Android 沉浸式 UI 實現及原理

發表於2016-07-04

沉浸式體驗

首先別吐槽沉浸式這個名詞吧,畢竟這各名字是廣為人知並且比透明狀態列加透明導航欄更酷。充分使用整個螢幕將這2個系統檢視融入自己APP也算沉浸式體驗吧。

首先2個名詞:
StatusBar

680540-3ed6ad6b208e363b

Paste_Image.png

NavigationBar

680540-e90d063678e26379

Paste_Image.png

下面是Google的官方標準模版:

680540-8baa1a787a21495f

未標題-1.jpg

在官方示例中:
StatusBar是一個半透明陰影,View可以伸展到其後面。
NavigationBar是純黑不能使用的。

Google提供NavigationBar的透明與使用的可能,卻沒有推薦使用。個人覺得是為了給

680540-bc4951fc8e5c34cd

Paste_Image.png

Bottom navigation
做準備。這裡不討論Bottom navigation的優劣(我是Bottom navigation黑)。

下面是B站的:

680540-a16811099afa353e

QQ圖片20160525195336.jpg

不可否認使用NavigationBar空間對多下巴手機是種拯救。
(Google自己推的虛擬按鍵,卻自己放棄了屏佔比這一大優勢。)

好了,B站的UI就是我所期望的UI。下面我們就來實現它。

style的配置

android從4.4開始,開始支援UI使用StatusBar與NavigationBar的範圍。
所以要進行下面的配置:

在value中的styles.xml中設定

在value-v19中的styles.xml中設定(為了相容4.4)

在value-v21中的styles.xml中設定

然後使用AppTheme這個主題,這是1個示例,應該看得出來吧。只要在你的AppTheme的v19版本和v21版本新增了相應屬性就好。

使用ToolBar

當你使用了StatusBar的部分,就不要再使用ActionBar了。
現在基本都會使用ToolBar了吧。還不會可以參考 ToolBar的使用

然後效果如下:

680540-81116cc108ea62c0

QQ圖片20160525195351.jpg

然後這裡就有2個問題:

1. Toolbar到了StatusBar的下面(為了凸顯問題給Toolbar設了顏色)
2. View在NavigationBar下難以點選

這2個問題也是理所應當就應該存在的。
解決方法

FitSystemWindowLayout

這裡就先說結果吧,使用FitSystemWindowLayout,我為此做了很多適配工作。
這是標準介面:

680540-f4e912512e436d8d

QQ圖片20160525195401.jpg

這個庫提供自動適應StatusBar與NavigationBar的幾個Layout。在XML中設定即可。
這是上面標準UI的XML:

FitSystemWindow的原理

Android4.4與Android5.0的Insets處理機制完全不同。

Android 5.0的機制:

ViewRootImpl.java中掌管View繪製的函式。

SystemBar的尺寸在WindowInsets 中表示出來,比如Insets:(0, 63 , 0, 126)。表示StatusBar高度63,NavigationBar高度126.
dispatchApplyWindowInsets 將WindowInsets 從View樹頂部開始分發。

這個方法很簡單。在View樹中分發Insets,先序遍歷。一旦被消費就終止分發。可以看到處理WindowInsets 主要是2個方式。

自定義Insets處理方式的方法1

給目標View註冊監聽
View接收到Insets。會先判斷自己是否被註冊了監聽,監聽是指這個,在這個監聽裡能夠收到Insets。並依據自己情況處理。

自定義Insets處理方式的方法2

重寫onApplyWindowInsets
先看看預設的實現。

重點來了fitSystemWindowsInt.它實質性的判斷並設定了Padding。

FITS_SYSTEM_WINDOWS這個flag有2個來源:
程式碼手動設定:

在XML中設定android:fitSystemWindow="true"

這就很明顯了。
設定了fitSystemWindow,預設就會消費掉Insets,並設定padding。如果沒有設定,會繼續遍歷直到被某個View消耗。

其實上面的程式碼是精簡後的,實際上對4.4的機制做了一些相容處理。為了便於理解刪掉了。

Android 4.4的機制:

4.4的機制比5.0簡單得多。

讓DecorView執行fitSystemWindows

分發的過程變到了這裡。並且直接就應用了。
與5.0有很大不同(簡單了好多)。
重寫fitSystemWindows方法即可實現與5.0一樣的效果。

相關文章