此篇文章主要講解關於沉浸式狀態欄,程序全屏和分清狀態欄、ActionBar、ToolBar 的一些知識內容。主要是講解如何適配狀態欄。關於 ActionBar 和 ToolBar 的使用沒有細緻講解。java
文章最先發佈於個人微信公衆號 Android開發者家園 中
本文爲sydMobile原創文章,能夠隨意轉載,但請務必註明出處! 因爲我的精力有限,多個渠道發佈,排版可能會有問題。重點維護個人我的公衆號「 Android 開發者家園 」android
其實這篇主要是講解適配狀態欄的,在這其中可能有些讀者對狀態欄(StatusBar)、ActionBar、ToolBar、TitleBar有點混淆或者感受很混亂,因此就有了這其中的內容。bash
首先強調一點 StatusBar 和前面這幾種 Bar 是徹底的兩回事,其實 statusbar 應該寫成 status bar ,也就是咱們的狀態欄。沒錯就表示咱們 Android 中最上面顯示時間、通知的那一欄。微信
提及 TitlBar、ActionBar、ToolBar,要和 Android 的發展歷史有關了。網絡
在 Android 3.0 以前,設計上沒有美感之說,知識爲了完成功能,這個時候最上面樣式就是顯示當前頁面的 Title,也就是 TitleBar,這個時代的 Android 機都是有物理返回鍵的。這個時候就是充當一個 Title 的做用,這也就是 TitleBar。它的樣子是這樣的ide
上面顯示MyStudyDemo
的一欄就是 TitleBar 了。佈局
而後在 Android 3.0 API 11 開始注重美感了,引進了 HOLO 樣式,這個時候用 ActionBar代替了 TitleBar 了。這個時候的 Bar 的功能再也不僅僅限於展現標題了,有了不少的新功能。字體
Fragment 也是在 Android 3.0 的時候引入的,因此 Android 3.0 對於 Android 的發展史仍是很重要的。ui
最簡單的 ActionBarspa
值得注意的是 TitleBar 和 ActionBar 在本質上是同樣的,他們都不是咱們經常使用的控件的形式,而是綁定在 DecorView
中的,能夠經過 getWindow().setFeatureInt()
暴露出的幾個方法進行修改功能和樣式。
正是由於 ActionBar 是嵌套在 DecorView 中的,它不是一個獨立的控件,並且因爲國內的 Android 應用開發環境,通常都不遵循 Google 的那一套設計,因此運用起來很不靈活。隨後在 Android 5.0 推出了 ToolBar 控件,這是一個徹底獨立的控件,你能夠盡情的運用了。
好了,到這裏來應該完全分清楚這幾個 bar 了吧,這是 Android 的一個歷史發展造成的,能夠結合個人這篇文章 blog.csdn.net/sydMobile/a… 來詳細的看一下 Android 在樣式上的發展。
由於上面也說了 ActionBar 是在 Android 3.0 之後才引用的,可是真正的規範是在 Android 4.1 以及以上。因此在 Android 4.1 如下版本是不支持 ActionBar 的。這裏針對 ActionBar 的操做全是在 Android 4.1 以上運行的,不適用於 Android 4.1 如下版本。
說明:在 Android 4.4 以前狀態欄一直就是黑色的,在 Android 4.4 中帶來了 windowTranslucentStatus
這一特性,這個時候才能夠給狀態欄設置顏色。在國內將這種狀態欄變色叫作沉浸式狀態欄,其實這種叫法是錯誤的,可是時間久了,你們都這麼叫了,就不追究了,就把這種狀態欄變色叫作沉浸式狀態欄了(這也是由國內互聯網發展太過迅速,忽略了不少細節點,相關方面的人才缺少,另外一個方面是國內的 Android 開發環境形成的,碎片化太過嚴重,不一樣的手機廠商關於這些又有不一樣的叫法)。
關於沉浸式和透明式概念說明
在谷歌官方中:
在 Android 4.4 Google 引入了能夠在閱讀電子書、玩遊戲、看電影時支持全屏模式(Immersive Mode 沉浸模式),同時也支持更改修改狀態欄的顏色。
能夠知道在官方是根本沒有 沉浸式狀態欄 這種說法的。只有 沉浸模式 就是其實就是出於全屏狀態。所謂的 」沉浸式狀態欄「,相似於下面圖的樣子:
上面也說了這種錯誤的叫法是不對的,沒有沉浸式狀態欄 ,這種樣式只是將內容 UI 設置成了全屏,把狀態欄設置成了透明。因此這種是叫作 狀態欄透明模式
先來幾組效果圖,從效果 1 開始逐漸遞進演示,這裏面的幾個重要參數會在後面具體說明,這裏先說明現象
在 Android 4.1 以上設置去除狀態欄或者認爲是狀態欄被內容佈局遮擋了(全屏)和去除 ActionBar
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(option);
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
// 狀況說明:採用這種方式全屏,若是你切換到別的應用程序,或者在通知欄下拉一下,狀態欄就會下來,咱們的 UI 佈局就會跑到狀態欄下面,和沒有設置的時候效果是同樣的。
複製代碼
效果圖:
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
// 能夠看到咱們在 option 中添加了一個 STABLE 屬性,這個屬性是用阿里保持咱們的 UI 視圖穩定的,使得它不會由於系統 UI 的變化而從新 layout 。記住這個屬性長和 FLAG_LAYOUT_XXX 這種屬性在一塊兒使用。STABLE 就是會始終給系統 UI 保留一個空間(無論系統 UI 有沒有消失,而且懸浮在咱們本身的 UI 視圖上面 )
// 能夠看到這種效果,狀態欄仍然還在,只是你仔細發現,原佈局有一部分被狀態欄給覆蓋了,也就是說這種方式的話,佈局延伸到了狀態欄。這個時候咱們只要設置狀態欄爲透明。就是咱們想要的透明狀態欄的那種效果了。
複製代碼
效果圖:
// 只須要在 2 的基礎上把狀態欄設置成透明就能夠了
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
if(Build.VERSION.SDK_INT >= 21){
// 這個方法只有 5.0 後才能夠用,也就是說 Android 5.0 之前不支持更改狀態欄顏色,這是說的是原生系統
// 小米的 ui 在 Android 5.0 以前也提供了修改方法
getWindow.setStatusBarColor(Color.TRANSPARENT);
}
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
// 這樣咱們的狀態欄就變成透明的了,就是人們常說的「沉浸式狀態欄」
複製代碼
// 主要是爲了驗證 STABLE 的做用,在 1 的案例中,咱們只用 FLAG_FULLSCREEN 屬性,會發如今切換應用或者觸碰系統 UI 的時候,這個時候咱們的狀態欄就會出來,而後咱們的 UI 佈局就會「被壓在」狀態欄的下面(其實是把咱們的佈局從新 layout 了)而後若是添加 STABLE 屬性呢?
if (Build.VERSION.SDK_INT >= 21){
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
// 結果就是 提早預留了一塊系統 UI 的控件,下拉的時候,狀態欄內容就會顯示出來。(這樣咱們的 UI 佈局是沒有被從新 layout 的)
複製代碼
// 所謂沉浸模式就是一開始咱們的 UI 佈局是全屏的,狀態欄和虛擬導航鍵也是隱藏的,當咱們須要的系統 UI 的時候,從狀態欄的位置下拉就能夠出現系統 UI,這個時候就須要一個新的屬性了 View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 須要在 Android 4.4 及其以上版本
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus && Build.VERSION.SDK_INT >=19){
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
);
}
}
// 當觸摸底部或者上部狀態欄的時候,導航欄和狀態欄就會出來,過一會就會消失,相似於遊戲中那樣。
複製代碼
Android 5.0 (API 21) 後支持直接修改狀態欄的顏色,在 Android 4.4(API 19)以前是不容許操做狀態欄的,也就是說在 Android 4.4 以前,咱們是無法對狀態欄進行任何操做的。
// 將狀態欄設置爲透明(須要 API 19) 設置成這種模式後,狀態欄會變成透明,咱們的內容佈局(只是咱們 Activity 對應的佈局,不包含 Window 中的 ActionBar)會佔據系統欄。相似於 getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | LAYOUT_STABLE); getWindow().setStatusBarColor(Color.TRANSPARENT);
// 首先設置狀態欄爲透明
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// 這個時候,咱們的佈局內容中佔據系統欄了,這個時候,咱們只須要本身來建立一個系統欄背景就能夠了。
View mStatusBarView = new View(context);
int screenWidth = 屏幕寬度;
int statusBarHeight = 狀態欄高度(是能夠獲取的);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(screenWidth,statusBarHeight);
mStatusBarView.setLayoutParams(params);
mStatusBarView.requestLayout();
// 獲取系統默認的根佈局
ViewGroup systemContent = findViewById(android.R.id.content);
// 這個就是咱們本身的佈局文件
ViewGroup userContent = systemContent.getChildAt(0);
// 添加到咱們的佈局中
userContent.addView(mStatusBarView,0);
複製代碼
// 方法一
getWindow().setStatusBarColor(int color );
// 方法二
樣式中: <item name="colorPrimaryDark">@color/colorAccent</item> 對應狀態欄顏色
複製代碼
關於狀態欄的文字顏色,是在 Android 6.0 纔開始能夠支持修改的
// 修改爲 黑色字體
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
複製代碼
setFitsSystemWindows(boolean is);
在直接調用這個方法的時候,只有咱們本身的根佈局(在 mContentParentParent 中,titleBar 的位置是固定的),調用才起做用。表示是否保留系統欄的空間。能夠在佈局屬性中設置。做用和給控件添加 "fitsSystemWindows" 屬性相同。
若是設置了這個屬性爲 true,那麼則是保留系統 UI 的位置(其實是固定了咱們的 UI 的高度,咱們 UI 的高度就是屏幕去掉系統欄高度後的高度),那麼這個時候你如何設置了 FLAG_LAYOUT_HIDE_NAVIGATION 是不起做用的,由於咱們的佈局高度已經肯定了,不可能延伸到系統欄。
複製代碼
// 方式一
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 方式二
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
// 方式三 style.xml 中配置
<style name = "fullScreen" parent="Theme">
<item name="android.windowFullscreen">true</item>
</style>
// 總結:
關於 addFlags 和改變 statusbar 顏色的方法在 getWindow 裏面
複製代碼
爲了說明頁面的佈局關係,這裏引入一張圖片(來自網上)
每一個 Activity 對應一個頁面,是不包括 status bar 的,不過可設置 status bar 顯示仍是不顯示,能夠設置 Activity 是否延伸到 status bar 的位置(確切的來講是 Window 窗口)
DecorView 是繼承自 FrameLayout 的。
其中 mContentParent 的 id 是 com.android.internal.R.id.content
mContentParent 經過這個 id 就能夠獲取到咱們本身的佈局的根佈局了。
titleBar 也有一個 id
相關文章:yifeng.studio/2017/02/19/…
更多資源請查看我的公衆號