Activity 全屏,沈浸式模式這一篇就夠了
本文由小鈣投稿。
小鈣的博客地址:
http://blog.csdn.net/zhangqinghuazhangzhe
1
概述
第一次在項目中要用到全屏功能的時候無從下手,然後就是去百度了。百度到的結果都是差不多的。不過直接把代碼貼過來的確是可以用的。但是除了知道怎麽做之外還想去理解它,因為只有理解了才能舉一反三嘛。好在在後來的時候看到了官方的文檔,寫的非常詳細。
我是官方文檔
(https://developer.android.com/training/system-ui/index.html)
接下來開始正題
…
…
…
先給出一些名詞方便下面的講解
StatusBar:
NavigationBar:
SystemBar 為:StatusBar 跟 NavigationBar 的統稱
設置全屏主要分為兩種方式:
4.0 之前采用的方式
4.0 之後新增的方式
2
4.0 以及之前設置全屏
因為 4.0 之前的系統已經很少了,所以這裏就簡單的說一下。
有兩種方式可以實現全屏:
使用全屏的主題
getWindow().addFlag(WindowManager.LayoutParams.FLAG_FULLSCREEN)
這種全屏方式是無法隱藏 NavigationBar 的(如果有 NavigationBar 的話),因為 NavigationBar 是在 4.0 以後才引入的。使用這種方式設置全屏的特點是,離開了 App 後再進入 App 時,依然處於全屏模式,只能清除掉全屏標誌位才能退出全屏。
3
4.1 以及之後設置全屏
4.1 以及之後使用 View 的 setSystemUiVisibility() 來對 SystemBar 進行控制。
任何 View 都可以用來調用這個方法,只要它是可見狀態的。
下面先把要涉及到的 flag 分組列舉出來(所有的 flag 都是以 SYSTEM_UI_FLAG 作為前綴,所以下面將其省略)。
控制 SystemBar 相關:
FULLSCREEN
HIDE_NAVIGATION
LOW_PROFILE
布局相關:
LAYOUT_SCREEN
LAYOUT_HIDE_NAVIGATION
LAYOUT_STABLE
沈浸式相關 (4.4 引入):
IMMERSIVE
IMMERSIVE_STICKY
超前提示:
在離開 App 時,比如按了 home / 多任務鍵 會導致設置的控制 SystemBar 相關的 flag 被清除,而其他設置的 flag 不會受到影響。
3.1 FULLSCREEN
雖然寫的是 Fullscreen ,但其實只是隱藏 StatusBar。
看圖可以得出以下幾點:
點擊屏幕 StatusBar 不會顯示出來
從屏幕上邊緣往下滑可以讓 StatusBar 重新顯示
點擊 home / 多任務鍵再返回 App 時 StatusBar 重新顯示了出來,印證了超前提示裏所說的。而且 StatusBar 在顯示出來以後不會自動隱藏,這一點跟在 4.1 之前設置的全屏方式不一樣,因為設置的 FULLSCREEN flag 已經被清除了,如果想重新隱藏,需要重新設置該 flag。
StatusBar 的顯示 / 隱藏會使 ImageView 大小發生了變化
為了防止布局大小不會因為 StatusBar 的顯示 / 隱藏發生變化,有兩種 flag 可供選擇:
1. LAYOUT_STABLE
mDecorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
這裏有一點需要註意:設置多個標誌位時要用 | 連接起來,不能多次調用 setSystemUiVisibility。如:
mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
這樣的結果就是只有最後一次設置的 flag 生效,而之前設置的標誌位會被清除。也就是說上面的代碼中只設置了 LAYOUT_STABLE 而 FULLSCREEN 被清除了。所以如果想清除之前設置的所有 flag ,mDecorView.setSystemUiVisibility(0) 就可以了
這次布局並沒有延伸到 StatusBar 底下,所以大小也就不會受到它的影響
2.LAYOUT_FULLSCREEN
mDecorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
3.2 HIDE_NAVIGATION
protected void onCreate(Bundle savedInstanceState) {
mDecorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
Google 建議隱藏 NavigationBar 的同時將 StatusBar 一起隱藏。
與隱藏 StatusBar 時不同的是,隱藏了 NavigationBar 以後,點擊屏幕的任何位置都會導致設置的所有控制 SystemBar 相關的 flag 被清除,所以 SystemBar 重新顯示了出來。
這裏還需要註意的在這種模式下點擊屏幕點擊事件會被屏蔽,要等到 SystemBar 顯示出來以後再次點擊,事件才會傳遞到我們的布局中。
與 LAYOUT_FULLSCREEN 類似的是, LAYOUT_HIDE_NAVIGATION 可以讓布局內容延伸到 NavigationBar 的底部。
因為離開 App 後控制 SystemBar 相關的 flag 會被清除,所以可以按需在 onResume() 或者
onWindowFocusChanged() 中重新設置它們。
3.3 LOW_PROFILE
protected void onCreate(Bundle savedInstance) {
mDecorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LOW_PROFILE);
}
這種模式好像用的不多,作用是減少 StatusBar 中的圖標並使其變暗,將 NavigationBar 中的按鈕減弱成 3 個點。
直接上圖來說明該 flag 的效果吧:
3.4 IMMERSIVE
需要配合 View.SYSTEM_UI_FLAG_FULLSCREEN 和 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 一起設置
mDecorView.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);
可以看到設置了該 flag 以後,點擊屏幕不會讓 SystemBar 顯示出來。而在呼出 SystemBar 後,控制 SystemBar 相關的 flag 依然會被清除。
3.5 IMMERSIVE_STICY
跟 IMMERSIVE 不同的是,在該模式下呼出的 SystemBar 會在短暫的顯示後自動重新隱藏。在 SystemBar 顯示出來的時候點擊屏幕中心會立刻讓 SystemBar 重新隱藏。所以在模式下不會清除控制 SystemBar 相關的 flag。但是離開 App 時還是會被清除。
所以在回到 App 的時候要重新激活它:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
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);}
}
4
監聽 SystemBar 的變化
通常情況下我們需要能夠控制 SystemBar 的顯示與隱藏,所以就需要監聽 SystemBar 的狀態。
FULLSCREEN(4)
HIDE_NAVIGATION(2)
LOW_PROFILE(1)
括號中的數字是它們的值,現在讓我們回到代碼中。
onSystemUiVisibilityChange(int visibility) 中的 visibility 表示的是 LOW_PROFILE、FULLSCREEN 跟 HIDE_NAVIGATION 這三個值的和。
因為只有這 3 個值是跟控制 SystemBar 相關的。
也就是說從 visibility 的值就可以只知道我們設置了哪些 flag。
比如如果 visibility 為 4,說明設置了 FULLSCREEN;
如果 visibility 為 7 則說明 3 種 flag 都設置了。
所以當 visibility 為 0 時表示沒有設置任何控制 SystemBar 的 flag,也就說明了 SystemBar 處於顯示狀態。
為什麽 visibility 的值會是它們三個的和呢?因為我們在設置 flag 的時候是用 | 將多個 flag 連接在一起的, | 就相當於把它們的值加起來。
當 SystemBar 顯示或者隱藏的時候,該監聽器就會被觸發。但是如果使用的是 IMMERSIVE_STICKY ,在 SystemBar 被呼出的時候不會觸發該監聽器。
下面給出一個 Demo ,功能是點擊圖片時進入/退出全屏
這裏有一個問題,如果點擊稍微快一點的話就會出現只隱藏 StatusBar 而沒有隱藏 NavigationBar 的情況。如果有哪個小夥伴知道的話請告知一下。
希望這篇文章能給大家帶來一點點幫助。
大連男科醫院 http://www.liaoningnk.com/
大連專業婦科醫院 http://www.bohaifk.com/
Activity 全屏,沈浸式模式這一篇就夠了