為應用加上Android4.4新特性的全屏模式-沉浸模式(Full-screen Immersive Mode)。


Android4.4的發布帶來了新的特性-沉浸模式(Full-screen Immersive Mode),開啟后應用占據全屏,虛擬按鈕和系統欄隱藏,提高屏幕的利用率和沖擊力。

那么怎樣為我們的應用加入這個模式呢?先查看下Google的官方文檔,里面有完整的示例代碼。

 1 // This snippet hides the system bars.
 2 private void hideSystemUI() {
 3     // Set the IMMERSIVE flag.
 4     // Set the content to appear under the system bars so that the content
 5     // doesn't resize when the system bars hide and show.
 6     //開啟全屏模式
 7     mDecorView.setSystemUiVisibility(
 8             View.SYSTEM_UI_FLAG_LAYOUT_STABLE
 9             | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
10             | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
11             | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
12             | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
13             | View.SYSTEM_UI_FLAG_IMMERSIVE);
14 }
15 
16 // This snippet shows the system bars. It does this by removing all the flags
17 // except for the ones that make the content appear under the system bars.
18 //取消全屏模式
19 private void showSystemUI() {
20     mDecorView.setSystemUiVisibility(
21             View.SYSTEM_UI_FLAG_LAYOUT_STABLE
22             | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
23             | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
24 }

進入全屏后從屏幕上下放往里滑可重新喚出系統欄和虛擬按鈕,但是喚出后系統欄會蓋住一小部分內容,這個時候要給根layout設置一個高度為系統欄高度的Padding才能解決,后面會講到。

而且要再進入全屏模式還要再點擊一次按鈕。所以我比較推薦下面的模式,喚出的是透明的系統欄和虛擬按鈕,短暫的時間后系統欄和虛擬按鈕會自動隱藏。

只需要把View.SYSTEM_UI_FLAG_IMMERSIVE改為View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY。

 1 @Override
 2 public void onWindowFocusChanged(boolean hasFocus) {
 3         super.onWindowFocusChanged(hasFocus);
 4     if (hasFocus) {
 5         decorView.setSystemUiVisibility(
 6                 View.SYSTEM_UI_FLAG_LAYOUT_STABLE
 7                 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
 8                 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
 9                 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
10                 | View.SYSTEM_UI_FLAG_FULLSCREEN
11                 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);}
12 }

如果你的應用有ActionBar的話也會被隱藏掉,退出全屏模式后ActionBar會重新出現,但是和系統欄一樣會覆蓋在你的布局上。

這是開啟前:                                  這是開啟后:                                   關閉全屏后按鈕被標題欄覆蓋掉了

                  

這時候就需要用到ActionBar的覆蓋模式了(Overlaying the Action Bar),具體設置請看Google的文檔

如果你用的是support v7兼容包的ActionBar可能會設置不了樣式,請看我之前的一篇隨筆來解決這個問題。

要解決被覆蓋的問題需要動態設置根布局的內邊距,請看下面的設置:

 1 public class MainActivity extends Activity implements OnClickListener {
 2     private RelativeLayout rlLayout;
 3 
 4     @Override
 5     protected void onCreate(Bundle savedInstanceState) {
 6         super.onCreate(savedInstanceState);
 7         setContentView(R.layout.activity_main);
 8         //設置ACtionBar
 9         ActionBar actionBar = getActionBar();
10         actionBar.setDisplayHomeAsUpEnabled(true);
11         actionBar.setHomeButtonEnabled(true);
12 
13         rlLayout = (RelativeLayout) findViewById(R.id.rlayout);
14         Button mButtonOn = (Button) findViewById(R.id.button_on);
15         Button mButtonOff = (Button) findViewById(R.id.button_off);
16         mButtonOn.setOnClickListener(this);
17         mButtonOff.setOnClickListener(this);
18     }
19 
20     public void onClick(View v) {
21         //獲得根視圖
22         View view = getWindow().getDecorView();
23         switch (v.getId()) {
24         case R.id.button_on:
25             //進入沉浸模式
26             hideSystemUI(view);
27             //把內邊距設為0
28             rlLayout.setPadding(0, 0, 0, 0);
29             break;
30         case R.id.button_off:
31             //退出沉浸模式
32             showSystemUI(view);
33             //獲得系統欄高度
34             Rect frame = new Rect();
35             view.getWindowVisibleDisplayFrame(frame);
36             //需要設置的內邊距為ActionBar高度和系統欄高度相加
37             int paddingTop = getActionBar().getHeight() + frame.top;
38             rlLayout.setPadding(0, paddingTop, 0, 0);
39             break;
40         }
41 
42     }
43 
44     @Override
45     public boolean onCreateOptionsMenu(Menu menu) {
46         getMenuInflater().inflate(R.menu.main, menu);
47         return true;
48     }
49 
50     @SuppressLint("NewApi")
51     public static void hideSystemUI(View view) {
52         view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
53                 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
54                 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
55                 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
56                 | View.SYSTEM_UI_FLAG_FULLSCREEN
57                 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
58     }
59 
60     @SuppressLint("NewApi")
61     public static void showSystemUI(View view) {
62         view.setSystemUiVisibility(
63                 View.SYSTEM_UI_FLAG_LAYOUT_STABLE
64                 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
65                 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
66     }
67 }
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2     xmlns:tools="http://schemas.android.com/tools"
3     android:id="@+id/rlayout"
4     android:layout_width="match_parent"
5     android:layout_height="match_parent"
6     android:paddingTop="?android:attr/actionBarSize"
7     tools:context=".MainActivity" >

如果我需要把一個應用里的所有activity都設為沉浸模式呢?只需要重寫activity的onResume()方法,然后把這個activity設為父類,讓所有的activity繼承它就可以了。

因為每創建一個新的activity都要檢測是否開啟全屏模式,而如果在后一個activity里設為全屏后返回上一個activity時也要檢測是否變成全屏模式。

下面是我的應用里onResume()的設置,因為我的應用要兼容android2.1所以Actionbar用的是support v7包,獲取Actionbar是用getSupportActionBar();

如果你的應用需要在進入沉浸模式后通知其他UI改變的話可以加入一個監聽器View.OnSystemUiVisibilityChangeListener()。

檢測當前activity是否為沉浸模式的方法是

1 int status = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
2       | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3       | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
4       | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
5       | View.SYSTEM_UI_FLAG_FULLSCREEN
6       | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
7 view.getSystemUiVisibility() == status;

如果在后面的activity里退出了沉浸模式。那么返回前一個activity的時候,前一個activity要檢查下是否要退出沉浸模式。在onResume()里面檢查就可以。

 1 protected void onResume() {
 2          // 判斷是否是android4.4
 3          if (SystemInfo.getSystemVersion() > 18) {
 4              SharedPreferences sPreferences = getSharedPreferences("AppBrightness", 0);
 5              // 讀取存在SharedPreferences里的設置
 6              boolean Fullscreen = sPreferences.getBoolean("Fullscreen", false);
 7              ActionBar actionBar = getSupportActionBar();
 8              // 獲得根視圖
 9              View view = getWindow().getDecorView();
10              // 獲得根布局
11              ViewGroup vGroup = (ViewGroup) (view.findViewById(android.R.id.content));
12              // 用於判斷應用是否已經退出沉浸模式了。
13              int status = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
14                         | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
15                         | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
16                         | View.SYSTEM_UI_FLAG_VISIBLE
17                         | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
18              // 判斷是否要開啟沉浸模式
19              if (Fullscreen) {
20                  // 需要開啟沉浸模式則把actionbar先隱藏掉,不然在Activity跳轉時會閃出來。
21                  actionBar.hide();
22                  // 進入沉浸模式
23                  SystemUI.hideSystemUI(view);
24                  // 在根布局獲得第一個控件,也就是最上層的layout。把內邊距設為0
25                  vGroup.getChildAt(0).setPadding(0, 0, 0, 0);
26              } else if (view.getSystemUiVisibility() == status){          
27                  // 如果應用已經退出沉浸模式,但是這個activity還是在沉浸模式內,則退出沉浸模式。
28                  actionBar.show();
29                  SystemUI.showSystemUI(view);
30                  // 獲得系統欄高度和actionbar高度,設置內邊距。
31                  Rect frame = new Rect();
32                  view.getWindowVisibleDisplayFrame(frame);
33                  vGroup.getChildAt(0).setPadding(0, actionBar.getHeight() + frame.top, 0, 0);
34              }
35          }
36          super.onResume();
37      }
1 public static int getSystemVersion() { //這是獲取系統版本的方法
2         int ver = android.os.Build.VERSION.SDK_INT;
3         return ver;
4     }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM