在我做 Android 開發(fā)之前,我就發(fā)現(xiàn)有些 App 的狀態(tài)欄和導航欄有透明效果,或者是沉浸式效果,比如說酷安的客戶端,是像這個樣子的:
雖然只是簡單的改變,但相對于傳統(tǒng)的上下兩個黑條來說,視覺效果會美觀很多,我當時挺糾結很多主流應用沒有這種效果,還特意安裝了一個 xposed 框架的模塊來強制實現(xiàn)沉浸式狀態(tài)欄和導航欄,不過貌似那個模塊會影響性能,從那時我就決定,如果將來我做 Android 開發(fā),一定會讓我開發(fā)的應用都使用這種效果,如今終于實現(xiàn)啦!
開源庫
經(jīng)過對大量應用的觀察,我發(fā)現(xiàn)這種透明狀態(tài)欄和導航欄或者叫沉浸式狀態(tài)欄和導航欄的效果主要有以下幾種:
1、自定義顏色的狀態(tài)欄和導航欄;
2、半透明的狀態(tài)欄和導航欄;
3、完全透明的狀態(tài)欄和導航欄(其實就是第二種的極限狀態(tài),我更喜歡 叫這種為沉浸式狀態(tài)欄和導航欄);
4、隱藏狀態(tài)欄和導航欄。
效果分別如下:
自定義顏色
半透明
完全透明
隱藏
事實上,在 github 上也有不少關于這方面的開源項目,不過這些開源項目大多只是針對狀態(tài)欄實現(xiàn)了透明或者沉浸式的效果,而對下方的導航欄并沒有做相應的處理,于是我自己寫了一個針對狀態(tài)欄和導航欄都實現(xiàn)透明或者沉浸式的效果的開源庫,地址如下:
UltimateBar
https://github.com/Zackratos/UltimateBar
這里要特別說明一下,狀態(tài)欄和導航欄透明是在 Android 4.4 開始支持的,但是 Android 4.4 的實現(xiàn)原理和 Android 5.0 以上的實現(xiàn)原理并不一樣,這就導致如果在 Android 5.0 以上如果使用 Android 4.4 的實現(xiàn)方法會出現(xiàn)顯示效果不一致的問題,我寫的這個庫分別對 Android 4.4 和 Android5.0 以上做了處理,使它在不同的系統(tǒng)版本下顯示效果達到高度統(tǒng)一,使用這個庫,首先需要添加依賴:
compile'org.zackratos:ultimatebar:1.0.3'
接下來對上面四種情況分別作介紹。
自定義的狀態(tài)欄和導航欄
要設置自定義顏色的狀態(tài)欄和導航欄只需要在 onCreate 方法中調用如下代碼:
那么他的內部是怎么實現(xiàn)的呢,查看源碼可以發(fā)現(xiàn),內部源碼是這樣的:
我們可以看到第一個方法里面?zhèn)魅肓藘蓚€參數(shù),第一個參數(shù)是自定義的顏色值,第二個參數(shù)是顏色深度值,最小為 0,最大為 255,當深度值為 0 時,狀態(tài)欄和導航欄的顏色就是第一個參數(shù)傳入的顏色值,即為第二個方法中的情況;當深度值不為 0 時,會根據(jù)深度值計算得到最終的顏色值,然后設置到狀態(tài)欄和導航欄上面。
正如前面所說,這里分別針對 Android 4.4 和 Android 5.0 以上做了不同處理,首先來看 Android 5.0 以上的情況,事實上 Android 5.0 以上的實現(xiàn)非常簡單,因為 Android 5.0 以上可以直接設置狀態(tài)欄和導航欄的顏色,所以只需要先得到最終的顏色值,然后調用 setStatusBarColor 和 setNavigationBarColor 方法進行設置就好了。然后 Android 4.4 稍微麻煩一點,首先必須要添加 FLAG_TRANSLUCENT_STATUS 這個 flag 來把狀態(tài)欄設置為透明,然后再在狀態(tài)欄上面添加一個 view 來保證狀態(tài)欄的顏色,然后再調用 navigationBarExist 方法來判斷當前手機是否存在導航欄,如果存在,對導航欄做同樣的處理,最后必須調用 setRootView 方法,這個方法是干嘛的呢,看一下它的代碼:
可以看到,這個方法是用來設置布局的子 view 的 fitsSystemWindows 參數(shù)的,相當于在布局中添加 android:fitsSystemWindows="true",如果不調用這個方法,就會導致布局中的內容覆蓋到狀態(tài)欄和導航欄上面了。
半透明的狀態(tài)欄和導航欄
半透明狀態(tài)欄和導航欄的使用方法也非常簡單,只要在 onCreate 方法中調用以下代碼:
同樣的看一下它的內部實現(xiàn),如下:
兩個參數(shù)分別表示顏色和透明度,透明度最小為 0,最大為 255,對于 Android 5.0 及以上,需要先添加 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,SYSTEM_UI_FLAG_LAYOUT_STABLE 三個 flag,以保證布局的內容可以覆蓋到狀態(tài)欄和導航欄上面,然后同樣的調用 setStatusBarColor 和 setNavigationBarColor 方法來設置狀態(tài)欄和導航欄顏色,不過這里的顏色都是經(jīng)過計算的半透明的顏色,對于 Android 4.4,跟之前的自定義顏色一樣,首先需要添加 FLAG_TRANSLUCENT_STATUS 這個 flag 保證狀態(tài)欄透明,然后再在狀態(tài)欄上添加一個半透明的 view,然后調用 navigationBarExist 方法判斷導航欄是否存在,如果存在,也做相同的處理,這里要注意,因為半透明狀態(tài)欄和導航欄需要布局內容覆蓋到狀態(tài)欄和導航欄上面的效果,所以在這里不能調用 setRootView 方法。
完全透明的狀態(tài)欄和導航欄
其實完全透明的狀態(tài)欄和導航欄就是半透明的狀態(tài)欄和導航欄中當透明度為 0 的情況,只需在 onCreate 方法中調用如下方法:
查看它的內部實現(xiàn)可以發(fā)現(xiàn)它是這么調用的:
就是半透明狀態(tài)欄和導航欄的特殊情況,不做過多介紹了。
隱藏狀態(tài)欄和導航欄
這種情況比較常見了,一般玩游戲,看視頻就是這種效果,這種效果的實現(xiàn)有點特殊,必須重寫 Activity 的 onWindowFocusChanged 方法,如下:
它的內部實現(xiàn)也比較簡單,如下:
就是添加幾個 flag,這是固定寫法,也不做過多介紹了。
針對DrawerLayout的實現(xiàn)
還有一種特殊情況,就是對于 DrawerLayout,上面的方法會出現(xiàn)一些問題,達不到想要的效果,這里針對 DrawerLayout 做了特殊處理,一般來說,對于 DrawerLayout 只要實現(xiàn)自定義顏色的狀態(tài)欄和導航欄效果就好了,其他情況就不用考慮了,可以在 onCrate 調用如下代碼:
但是這樣其實還是不夠的,還必須要在布局文件中在 DawerLayout 的子 view 的主界面添加 android:fitsSystemWindows="true",就像這樣:
注意,這里是在 DawerLayout 下面的主界面添加,DawerLayout 本身以及它下面的抽屜都不能添加,原因后面會說明,然后同樣看一下內部實現(xiàn):
這里稍微有點復雜,參數(shù)的傳遞和前面是一樣的,就不多解釋了,對于 Android 5.0 以上的情況,首先添加前面兩個 flag 保證布局內容能夠覆蓋到狀態(tài)欄上面,然后判斷是否存在導航欄,如果存在,再添加第三個 flag 保證布局內容可以覆蓋到導航欄上面,然后狀態(tài)欄和導航欄都設為透明色,此時相當于上面的完全透明的狀態(tài)欄和導航欄,最后再分別在狀態(tài)欄和導航欄上面添加一個 view 保證狀態(tài)欄和導航欄有顏色,這樣就既保證了 DrawerLayout 可以覆蓋到狀態(tài)欄和導航欄上面,又保證了 DrawerLayout 下面的主布局內容不會覆蓋到狀態(tài)欄和導航欄上面,最后的效果就是抽屜的內容是覆蓋到狀態(tài)欄和導航欄上面的,而住布局的內容不會覆蓋到狀態(tài)欄和導航欄的上面,然后對于 Android 4.4,其實和前面正常情況的設置自定義顏色的狀態(tài)欄和導航欄是一樣的,只是這里沒有調用 setRootView 方法,而是在 DrawerLayout 下面的主布局中添加了 android:fitsSystemWindows="true",同樣實現(xiàn)了抽屜的內容可以覆蓋到狀態(tài)欄和導航欄上面,而主布局的內容不會覆蓋到狀態(tài)欄和導航欄上面,最后的效果如下圖
抽屜未抽出
抽屜抽出一半
抽屜完全抽出
大致內容也就這么多了,最后再把這個庫的地址貼一遍:
https://github.com/Zackratos/UltimateBar
本文章選自郭霖郭大嬸,希望為您帶來幫助,如果喜歡的請點贊或者關注一下。