一直以來,iOS 設備上狀態欄背景色和圖標文字顏色的靈活可變性始終受到設計人員的青睞,有意地恰當地融入到 App 的各類界面設計當中,更好地提高用戶體驗。php
因爲系統的限制,在老版本的安卓系統中,Android App 沒法作到這些,產生一些設計上的遺憾。幸運的是,自 4.4 版本(API 19)之後,Android 系統開始支持狀態欄的定製,並被歸入 Android 設計規範當中,Android App 在設計上邁出了重要的一步。html
通常來講,Android 默認的狀態欄樣式表現爲黑底白字,若是咱們應用的標題欄背景色也爲黑色,那就能與狀態欄很好地銜接在一塊兒,體驗極佳。反之,若是爲其餘的顏色,整個界面的呈現效果就會大打折扣。java
幸運的是,Android 4.4 版本開始,系統提供了相應的 API,支持狀態欄全透明化,界面 Content View 能夠延伸到狀態欄上,填充狀態欄背景色。而在 Android 5.0 版本開始,系統在此基礎上作了進一步優化和規範,可以實現動態改變狀態欄背景色,在透明度上默認呈現爲半透明化,可定製化程度更高。android
在此基礎上,最終要作到咱們的應用呈如今 Android 各個系統版本上的效果如圖所示:git
關於 Android 4.4 版本開始的狀態欄變化,許多人喜歡稱之爲「沉浸式狀態欄」,但從系統提供的 API 命名上能夠看出,核心詞彙爲 「Translucent」,故準確來說,這種效果又應該稱之爲「透明狀態欄」。知乎上對於這兩種叫法也很有爭議,具體內容可參考話題:爲何在國內會有不少用戶把「透明欄」(Translucent Bars)稱做 「沉浸式頂欄」?。可能對於設計師而言,沉浸式仍是透明式的稱呼有所區別,但對於廣大開發者而言,無足輕重,咱們所關注的應該是如何實現這種效果,並可以很好的兼容到各個版本中。github
通常來講,目前在 Android 項目中咱們都會使用 Toolbar 替代 ActionBar 來實現導航欄,除此以外,要實現透明狀態欄效果,還須要瞭解兩個相關 API,下面逐一介紹一下:windows
一:api
<item name="android:windowTranslucentStatus">true</item>複製代碼
也能夠在代碼中實現(聽說,在代碼中實現兼容性更好,style 資源中設置的方式在某些國產手機廠商定製的系統中存在一些問題):微信
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
local LayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
}複製代碼
顧名思義,該屬性可以實現透明狀態欄效果,是在 Android 4.4 版本引入的,也就是兼容至 API 19 及以上版本。使用該屬性設置主題後,內容佈局向上延伸至狀態欄,而且在不一樣版本的系統中呈現效果也有所區別,如圖所示:app
顯然,在 API 19 及更高版本上,Toolbar 內容延伸至狀態欄上去了,出現重疊問題,此時,就須要使用到另外一個屬性了。
二:
android:fitsSystemWindows="true"
Boolean internal attribute to adjust view layout based on system windows such as the status bar. If true, adjusts the padding of this view to leave space for the system windows. Will only take effect if this view is in a non-embedded activity.
用在 layout 佈局文件中。官方文檔給出了很明確的介紹,大體是說可以將使用該屬性的視圖與系統窗口(如狀態欄)保持必定的 padding 間距。因此若是咱們在 toolbar 中設置了該屬性,就可以解決 <item name="android:windowTranslucentStatus">true</item>
配置帶來的視圖延伸問題,使呈現效果達到文章開始所示圖中的效果。
res/values/styles 文件中定義基礎主題樣式:
<style name="BaseTheme" parent="Theme.AppCompat.Light.NoActionBar"/> <style name="AppTheme" parent="BaseTheme"> </style>複製代碼
res/values-v19/styles 文件中定義兼容主題樣式:
<style name="AppTheme" parent="BaseTheme"> <item name="android:windowTranslucentStatus">true</item> </style>複製代碼
而後在 AndroidManifest.xml 文件中使用全局主題樣式:
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="Samples" android:supportsRtl="true" android:name=".MyApplication" android:theme="@style/AppTheme">
......複製代碼
新建一個 layout 佈局文件,單獨定義 toolbar 內容,在應用中的其餘 Activity 界面佈局中使用 include 標籤潛入引用:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/tb_toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="?actionBarSize" android:background="@color/colorPrimary" android:fitsSystemWindows="true" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:title="@string/app_name" app:titleTextColor="@android:color/white">
</android.support.v7.widget.Toolbar>複製代碼
這裏使用 android:fitsSystemWindows="true"
屬性解決內容試圖向上延伸的問題。實際上,也可使用 android:paddingTop="@dimen/toolbar_padding_top"
的方式解決,toolbar_padding_top 間距爲狀態欄高度,在大多數機器上狀態欄高度爲 25dp,固然也能夠經過代碼動態獲取狀態欄高度並設置到 Toolbar 的 paddingTop 屬性上。須要注意的是,這裏要作兼容判斷,好比在 res/values/dimens.xml 中定義toolbar_padding_top 高度爲 0dp,在 res/values-v19/dimens.xml 中爲 25dp,確保兼容 Android 4.4 如下版本。
基本上,作到這些就可以實現文章開頭處圖中的效果。值得注意的是,有時候若是想在 Android 5.0 及以上版本的系統中也作到全透明效果,或者說狀態欄與導航欄的顏色一致,還能夠作進一步兼容處理,畢竟自 5.0 版本開始,系統對於狀態欄背景色的定製提供了更好的 API。如 res/values-v21/styles.xml 中定義:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="BaseTheme"> <item name="android:colorPrimary">@color/colorPrimary</item> <item name="android:colorPrimaryDark">@color/colorPrimary</item> <item name="android:colorAccent">@color/colorAccent</item> </style>
</resources>複製代碼
說明一點,使用這種處理方式後,5.0 系統中應用的狀態欄背景色可隨意定製,同時與使用 <item name="android:windowTranslucentStatus">true</item>
樣式有所不一樣的是,該處理方式不會引發內容視圖的向上延伸,因此不須要在 layout 佈局文件中額外添加 android:fitsSystemWindows="true"
屬性。固然,添加了也無所謂,畢竟還要兼容 4.4 到 5.0 之間的版本。
前面咱們說過,雖說 4.4 版本開始,能夠實現透明狀態欄效果,也就是能夠經過各類手段實現修改狀態欄背景色,可是狀態欄圖標和文字的顏色默認爲白色,這個是沒法像 iOS 系統那樣,根據應用的總體色調動態修改。若是剛好 Toolbar 的背景色爲白色,爲了保持一致,將狀態欄背景色調爲白色的話,就會與狀態欄的白色內容發生衝突,致使其內容沒法凸顯,這個體驗確定沒法被用戶接受。
因此,碰見這種 Toolbar 或者說導航欄背景色爲白色的狀況,通常有兩種處理方式:第一種,不修改狀態欄背景色,一般默認爲黑色背景白色內容;第二種,修改狀態欄背景色爲淡黑色,這樣既能顯示狀態欄內容,又能與白色導航欄弱顯銜接,好比支付寶 App 就是這麼作的:
像上圖這種處理方式較黑色狀態欄來講,相對緩和一些,那能不能作到修改狀態欄內容的顏色呢,好比白底黑字?你們知道,Android 系統是開源的,國內的各家手機廠商都作了一些本身的定製,像部分廠商定製的系統就提供了相應的 API 供開發人員作適配工做。好比,部分廠商就提供了相應的 API 來修改狀態欄內容顏色,實現狀態欄白底黑字效果,如圖:
具體作法就是,在代碼中判斷系統類型,與提供修改狀態內容顏色的系統匹配,使用其特定的 API 操做便可。目前開放這種定製 API 的系統已知有 MIUI 和 Flyme 系統,具體實現代碼可參考:
其實,在 Android 6.0(API 23)及更高的版本上,系統也開始提供了對應的 API 來實現淺色調背景的狀態欄效果,可將狀態欄圖標和文字內容改成黑色樣式,實現方式爲:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}複製代碼
可是不知國內廠商在定製系統時是否對此有作處理,可否兼容這個 API ?不過,貌似微博 App 是這麼作的,你們感興趣地不妨一試。
除了上述 Toolbar 與 狀態欄在背景色上的銜接,App 中常見還有這樣一種設計,以微博我的主頁爲例,如圖所示:
頁面頂部的圖片內容延伸至狀態欄中,這種作法其實就是單獨使用 <item name="android:windowTranslucentStatus">true</item>
樣式,不在 layout 佈局文件中添加 android:fitsSystemWindows="true"
屬性便可。
還有一點,一般咱們會在資源文件中定義不一樣版本的主題樣式,再在 <application>
標籤中統一設置,而後全部的 Activity 都能使用這個主題樣式。但存在這樣一種狀況,Activity 由不一樣的 Fragment 組成,而後不一樣 Fragment 在狀態欄的呈現上有所不一樣,好比有的 Fragment 頂部使用 Toolbar 與狀態欄銜接,有的頂部直接使用圖片延伸至狀態欄上甚至不會用到 Toolbar,如圖所示:
因爲 Fragment 是沒法像 Activity 那樣在 AndroidManifest.xml 中單獨設置主題樣式的,因此這裏能夠這樣作:宿主 Activity 仍是使用透明樣式,以知足圖片延伸的 Fragment 頁面效果,其餘使用 Toolbar 的 Fragment,在其 Layout 佈局文件頂部單獨定義一個 View,讓其延伸至狀態欄,而後在代碼中根據不一樣版本系統設置其高度,4.4 版本如下設置該 View 高度爲0,4.4 及以上版本設置爲設備狀態欄高度,經過代碼獲取狀態高度的方式以下:
/** * 獲取狀態欄高度 * @param activity * @return */
public static int getStatusBarHeight(Activity activity){
Rect rect = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
return rect.top==0 ? 60 : rect.top;
}複製代碼
最後再補充一點,你們知道,長按 Toolbar 中 Menu Item 時會顯示一個 Toast 提示,內容來自 Item 定義時對應的 title 屬性,一般顯示如圖所示:
可是,若是你誤將 fitsSystemWindows
屬性設置在了 style 樣式文件中,好比:
<style name="BaseTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:fitsSystemWindows">true</item> </style>複製代碼
將會致使下圖效果:
可見,Menu Options Item 長按時彈出的 Toast 樣式沒了內容間距,顯然很醜。因此,記得將該屬性設置在正確的佈局文件中,不要設置成全局的。
以上即是有關 Android 4.4 開始的狀態欄背景色相關知識,能夠看出 4.4 、5.0 、6.0 版本做爲三個分水嶺,根據須要作好相關適配工做便可。還有一種經過 setSystemUiVisibility()
方法設置狀態欄的方式,還能實現狀態欄的顯示與隱藏交互效果,具體可參考這篇文章:
GitHub 上對於 Android 4.4 版本開始的狀態欄背景色的處理有一個開源庫,感興趣地朋友也可借鑑參考一番,地址以下:
有關 Toolbar 替換 ActionBar 的使用,能夠我以前總結的一篇文章,地址爲:
本文由 亦楓 創做並首發於 亦楓的我的博客 ,同步受權微信公衆號:技術鳥(NiaoTech),歡迎關注。