關(guān)于沉浸式狀態(tài)欄一詞的說(shuō)法從何而來(lái)我們無(wú)從考證。但這確實(shí)是個(gè)錯(cuò)誤的說(shuō)法
先引用官方的一段話。
Immersive full-screen mode
To provide your app with a layout that fills the entire screen, the new SYSTEM_UI_FLAG_IMMERSIVE flag for setSystemUiVisibility()(when combined with SYSTEM_UI_FLAG_HIDE_NAVIGATION enables a new immersivefull-screen mode. While immersive full-screen mode is enabled, your activity continues to receive all touch events. The user can reveal the system bars with an inward swipe along the region where the system bars normally appear. This clears the SYSTEM_UI_FLAG_HIDE_NAVIGATION flag (and the SYSTEM_UI_FLAG_FULLSCREEN flag, if applied) so the system bars remain visible. However, if you'd like the system bars to hide again after a few moments, you can instead use the SYSTEM_UI_FLAG_IMMERSIVE_STICKY flag.
Translucent system bars
You can now make the system bars partially translucent with new themes, Theme.Holo.NoActionBar.TranslucentDecor and Theme.Holo.Light.NoActionBar.TranslucentDecor.By enabling translucent system bars, your layout will fill the area behind the system bars, so you must also enable fitsSystemWindows for the portion of your layout that should not be covered by the system bars.
If you're creating a custom theme, set one of these themes as the parent theme or include the windowTranslucentNavigation and windowTranslucentStatus style properties in your theme.
以上是官網(wǎng)對(duì)于狀態(tài)欄的相關(guān)描述。那么什么意思呢?
-
Immersive full-screen mode (沉浸式全屏模式)
隱藏status bar(狀態(tài)欄)使屏幕全屏,讓Activity接收所有的(整個(gè)屏幕的)觸摸事件。 -
Translucent system bars (透明化系統(tǒng)欄)
使得布局侵入系統(tǒng)欄的后面,必須啟用fitsSystemWindows屬性來(lái)調(diào)整布局才不至于被系統(tǒng)欄覆蓋。
看到這里我要說(shuō):其實(shí)根本沒(méi)有什么沉浸式狀態(tài)欄,這就是一種錯(cuò)誤的說(shuō)法,錯(cuò)誤的概念。
如果到這里你還是有點(diǎn)迷糊那么我們?cè)倏磧煞Ч麍D,你就明白了。
沉浸式全屏模式:activity 占據(jù)整個(gè)屏幕,用戶(hù)交互時(shí)(拖動(dòng)狀態(tài)欄所在的位置)才會(huì)出現(xiàn)狀態(tài)欄和導(dǎo)航欄
透明狀態(tài)欄模式:狀態(tài)欄和導(dǎo)航欄依然可見(jiàn)但是呈現(xiàn)半透明狀態(tài)
注意:以上效果是在原生開(kāi)發(fā)系統(tǒng)上的效果,部分國(guó)產(chǎn)定制系統(tǒng)可能略有差異。請(qǐng)注意
實(shí)現(xiàn)方式:
其一Translucent Bar是4.4開(kāi)始有的特性;其二是5.0開(kāi)始,Google推出Material Design,使用Theme.Material(MD主題)或Theme.AppCompat主題并至少設(shè)置ColorPrimaryDark屬性就可以實(shí)現(xiàn)status bar半透明效果,所以本文只討論API19以上操作系統(tǒng)
- 通過(guò)Theme 方式實(shí)現(xiàn),官網(wǎng)有說(shuō)明android 中文官網(wǎng)
- 直接繼承官方Theme: 在Android API 19以上可以使用****.TranslucentDecor***有關(guān)的主題,自帶相應(yīng)半透明效果,Theme.Holo.NoActionBar.TranslucentDecor和Theme.Holo.Light.NoActionBar.TranslucentDecor兩種主題為新增加的,所以要新建values-v19文件夾并創(chuàng)建styles文件。
<style name="translusent"parent="android:Theme.Holo.Light.NoActionBar.TranlucentDecor">
</style>
在AndroidManifest 中設(shè)置使用該theme
<activity
android:name=".translucent.TranslusentThemeActivity"
android:label="@string/translucent_theme"
android:theme="@style/translusent">
</activity>
- 自定義主題Theme:繼承新主題時(shí)發(fā)現(xiàn)。這兩個(gè)新加的主題就是將windowTranslucentStatus ,windowTranslucentNavigation都設(shè)為true即可實(shí)現(xiàn)透明效果,那么只要我們自定義的主題也實(shí)現(xiàn)這兩個(gè)屬性即可。
在value-v19中新建style,代碼如下
<style name="translusent" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
由于 5.x開(kāi)始需要把顏色設(shè)置透明 ,所以我們必須新建個(gè)values-v21,并新建下面的主題
<style name="translusent" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<!--Android 5.x開(kāi)始需要把顏色設(shè)置透明,否則導(dǎo)航欄會(huì)呈現(xiàn)系統(tǒng)默認(rèn)的淺灰色-->
</style>
總結(jié):由主題來(lái)實(shí)現(xiàn)有一定的不確定性(少數(shù)情況下),可能因?yàn)槎ㄖ茩C(jī)器。模擬器等原因而達(dá)不到預(yù)期效果。但也不失為一種簡(jiǎn)單方便的實(shí)現(xiàn)方式
- 通過(guò)java代碼實(shí)現(xiàn)。下面我逐步實(shí)現(xiàn)
首先我們看下整體的代碼
public class TranslusentActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.translucent);
/**
* 由于21以下不能設(shè)置statusbar和NavigationBar的顏色所以實(shí)現(xiàn)透明化系統(tǒng)欄效果,仍然可以實(shí)現(xiàn)沉浸全屏模式
* */
if (Build.VERSION.SDK_INT >= 21) {
int option = getOption(6);
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(option);
getWindow().setStatusBarColor(Color.TRANSPARENT);//設(shè)置statusbar為透明色
getWindow().setNavigationBarColor(Color.TRANSPARENT);//設(shè)置NavigationBar為透明色
}
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
}
/**
* 由于各個(gè)flag都有相互制約性,不是單純的相互疊加效果。
* 所以也不必再在意每個(gè)flag的作用
*
* */
private int getOption(int type) {
int option = 0;
switch (type) {
case 0:
//隱藏statusbar的效果,當(dāng)與用戶(hù)交互時(shí)flag失效
option= View.SYSTEM_UI_FLAG_FULLSCREEN;
break;
case 1:
//隱藏導(dǎo)航欄,當(dāng)與用戶(hù)交互時(shí)(如拖動(dòng))該flag失效
option= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
break;
case 2:
//全部隱藏都不透明,當(dāng)有用戶(hù)交互,比如點(diǎn)擊拖動(dòng)。flag就會(huì)失效
option= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN;
break;
case 3:
//為設(shè)置statusbar實(shí)現(xiàn)透明鋪墊,將statusbar移動(dòng)到圖層的最上面,
// 當(dāng)設(shè)置statusbar為透明色的時(shí)候就可以實(shí)現(xiàn)沉浸效果
// 再調(diào)用setStatusBarColor
// 整個(gè)statusbar顯示為透明色
option=View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
break;
case 4://半透明效果
//這個(gè)模式也是為實(shí)現(xiàn)透明做鋪墊,將statusbar,Navigationbar 移動(dòng)到圖層的最上面,
// 當(dāng)設(shè)置statusbar,NavigationBar設(shè)置為透明色的時(shí)候就可以實(shí)現(xiàn)沉浸效果
// 再調(diào)用setStatusBarColor,setNavigationBarColor,設(shè)置為透明色。即可
option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
break;
case 5:
//隱藏導(dǎo)航欄,有SYSTEM_UI_FLAG_IMMERSIVE,
// 拖動(dòng)時(shí)隱藏導(dǎo)航欄的flag依然有效。
// 沒(méi)有SYSTEM_UI_FLAG_IMMERSIVE,隱藏導(dǎo)航欄的flag立刻失效
//SYSTEM_UI_FLAG_IMMERSIVE_STICKY和SYSTEM_UI_FLAG_IMMERSIVE效果相同,
// 只是幾秒鐘后隱藏導(dǎo)航欄的flag 又會(huì)生效
//這時(shí)候如果設(shè)置setStatusBarColor顏色為透明色,
// statusbar只會(huì)顯示為白色。。因?yàn)樽钕旅娴牡咨煌该? option=View.SYSTEM_UI_FLAG_IMMERSIVE
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
break;
case 6:
//綜合應(yīng)用,當(dāng)交互時(shí)導(dǎo)航欄,statusbar出現(xiàn)。失去焦點(diǎn)時(shí)消失
option=View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
|View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
break;
default:
//隱藏statusbar的效果,當(dāng)與用戶(hù)交互時(shí)flag失效
option= View.SYSTEM_UI_FLAG_FULLSCREEN;
break;
}
return option;
}
/**
* 19以上實(shí)現(xiàn)沉浸式全屏模式
*/
/*
@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_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}*/
}
調(diào)用view的setSystemUiVisibility(int option) 方法給View設(shè)置不同的flag,從而實(shí)現(xiàn)不同的布局效果
下面我們一步步分析,不同的flag及flag組合
-
case 0:View.SYSTEM_UI_FLAG_FULLSCREEN;
隱藏statusbar當(dāng)與用戶(hù)交互時(shí)flag失效 ,此時(shí)若設(shè)置statusbar的顏色為透明,則顯示為白色
隱藏statusbar效果圖 -
case 1: View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
隱藏Navigation當(dāng)與用戶(hù)交互時(shí)flag失效,
隱藏Navigationbar效果圖
-
**case2: **View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN;
隱藏statusbar和Navigationbar全部隱藏,當(dāng)與用戶(hù)交互時(shí)flag失效。
隱藏Navigationbar和statusbar效果圖
-
case 3:View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
為設(shè)置statusbar實(shí)現(xiàn)透明鋪墊,將statusbar移動(dòng)到圖層的最上面,當(dāng)設(shè)置statusbar為透明色的時(shí)候就可以實(shí)現(xiàn)沉浸效果
實(shí)現(xiàn)statusbar透明效果
-
case 4:View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
這個(gè)模式也是為實(shí)現(xiàn)透明做鋪墊,將statusbar,Navigationbar 移動(dòng)到圖層的最上面,當(dāng)設(shè)置statusbar,NavigationBar設(shè)置為透明色的時(shí)候就可以實(shí)現(xiàn)沉浸效果
statusbar、Navigationbar全透明效果 case 5: View.SYSTEM_UI_FLAG_IMMERSIVE
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
Kitkat新加入的Flag, 沉浸模式, 可以隱藏掉status跟navigation bar, 并且在第一次會(huì)彈泡提醒, 它會(huì)覆蓋掉之前兩個(gè)隱藏bar的標(biāo)記, 并且在bar出現(xiàn)的位置滑動(dòng)可以呼出bar
。case 6 : View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
隱藏導(dǎo)航欄,如有 SYSTEM_UI_FLAG_IMMERSIVE_STICKY 修飾 ,用戶(hù)交互時(shí)Navigation 會(huì)出現(xiàn),當(dāng)失去焦點(diǎn)時(shí)會(huì)再次隱藏**case 7: ** View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
|View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
綜合應(yīng)用,當(dāng);用戶(hù)交互時(shí)出現(xiàn)透明的statausbar和Navigationbar,當(dāng)失去焦點(diǎn)時(shí)再次隱藏statusbar和Navigationbar
以上的情況基本涵蓋了開(kāi)發(fā)中的大部分情況,很多的flag都具有相互依懶性,所以沒(méi)有必要去搞清楚每個(gè)flag的意思。需要的時(shí)候,當(dāng)做工具類(lèi)用就可以了。
由于21以下不能設(shè)置statusbar和NavigationBar的顏色,不能實(shí)現(xiàn)透明化系統(tǒng)欄效果,按著默認(rèn)顏色顯示。但仍然可以實(shí)現(xiàn)沉浸全屏模式 ,所以這里做了API版本的判斷。 如果你要在API19以上用,只需要修改API版本判斷即可(當(dāng)然那時(shí)候狀態(tài)欄、導(dǎo)航欄按著默認(rèn)顏色顯示)。代碼中被我注釋掉的部分即是
//19以上實(shí)現(xiàn)沉浸式全屏模式
@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_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
源碼由于和另一個(gè)Demo寫(xiě)在一起的,所以暫時(shí)沒(méi)上傳,后續(xù)另一篇文章完成以后會(huì)上傳的
多謝以下幾位大神的無(wú)私奉獻(xiàn),如有錯(cuò)誤歡迎指正,歡迎轉(zhuǎn)載,但請(qǐng)注明出處,謝謝
沉浸式狀態(tài)欄引發(fā)的血案
Android狀態(tài)欄微技巧,帶你真正理解沉浸式模式-郭神