1. 程式人生 > >Activity 全屏,沈浸式模式這一篇就夠了

Activity 全屏,沈浸式模式這一篇就夠了

instance public 4.0 edi 地址 developer 代碼 @override ref

  本文由小鈣投稿。

  小鈣的博客地址:

  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 全屏,沈浸式模式這一篇就夠了