8.Android 系統狀態欄沉浸式/透明化解決方案

轉載:http://www.jianshu.com/p/34a8b40b9308

前言

網上已經有不少有關於系統狀態欄的解決方案,這篇文章也不會有什麼新奇的解決方案,都是本人通過本身試驗,統計提煉出來的相對靠譜的一套解決方案.
若是是android大牛能夠忽略本文,怕讓您賤笑.只面向小白,幫助小白減小摸索的時間.css

關於術語

網上有不少爭論:html

你這狀態欄是變色龍狀態欄,不是沉浸式的
這應該是沉浸式的狀態欄吧,系統欄與actionbar顏色設爲一致android

我只想說去你妹的,老子只要本身的app的狀態欄能和主題顏色一致就好了,定義那麼多術語,讓我等小白情以何堪?
吐槽歸吐槽,但仍是不得不去試着理解下這些術語怎麼來的,引用這裏的一段話:ios

  1. 沉浸式全屏模式
    隱藏status bar(狀態欄)使屏幕全屏,讓Activity接收全部的(整個屏幕的)觸摸事件。
  2. 透明化系統狀態欄
    透明化系統狀態欄,使得佈局侵入系統欄的後面,必須啓用fitsSystemWindows屬性來調整佈局纔不至於被系統欄覆蓋。

所以,我就這樣理解了:git

沉浸式不就是隱藏狀態欄嘛,狀態欄不見了?這不就是app全屏模式嘛?wtf?程序員

而透明式式狀態欄就是讓app的內容佈局能夠擴展到系統狀態欄?這裏有個問題就是爲何能在系統狀態欄還顯示的狀況下,將內容佈局擴展到系統狀態欄?恩,這應該很好理解,就是Z座標系的做用了,系統狀態欄是覆蓋在內容佈局上面的,而且是透明的。github

貌似這裏所謂透明化系統狀態欄纔是本菜想要的,無論了,如今開始一一試驗,至於這概念理解的對不對,管他呢?那到底應該叫什麼,那我就叫自適應狀態欄,行不行?bash

前提條件

讓系統狀態欄顏色隨app主題顏色變化而變化這一設計,毫無疑問,也是向ios學習的:從android4.4開始引進的,而且在5.0進行了改進。所以,也只能將這一特性應用在android4.4以上的手機,沒法作到所有適配。記得stormzhang(貌似是)曾說過:app

做爲一個android程序員,還能有什麼比作出ios風格的app更感到悲哀的呢?哎...佈局

兩種狀況下的解決方案:

  1. 使用toolbar
    這種方案相對簡單,我的喜歡這種方案,本菜雖菜,但喜歡緊跟潮流。toolbar太好用了,
  2. 不使用toolbar

1. 使用toolbar的解決方案

這個方法參照了這裏,薄荷app的toolbar適配方案

其基本原理就是:
theme裏添加style: <item name="android:windowTranslucentStatus"> true </item>後,包含toolbar的內容佈局就能夠擴展至系統狀態欄,狀態欄會覆蓋在toolbar上,若是此時使用android:fitsSystemWindows="true",就能夠調整內容佈局(估計也是在根佈局上加padding)恢復到原來位置.可是,上面的解決方案確是給toolbar加上一個padding-top="25dp",這樣就能夠作到系統狀態欄的顏色和toolbar的顏色保持一致.具體方案能夠參照上面的薄荷app的方案連接.


簡述下步驟(只是簡述,有疑問請參照上面薄荷app的連接便可):

  1. 引入v7包,並在佈局裏添加toolbar
    compile ‘com.android.support:appcompat-v7:22.2.1’
  2. 在代碼中設置透明化:
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes(); local LayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags); }
    固然也能夠在theme的樣式文件裏添加style:<item name="android:windowTranslucentStatus">true</item>,效果相同,可是大神們都說樣式文件裏設置在某些型號裏不生效.ok,你們都在代碼裏設置就行了
  3. 給toolbar加上padding-top,toolbar代碼以下
    <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="@dimen/toolbar_padding_top" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:background="#30469b"> <TextView android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:text="@string/app_name"/> </android.support.v7.widget.Toolbar>
    4.其中android:paddingTop="@dimen/toolbar_padding_top"要在values中的styles文件裏設爲0dp,在values-v19的styles裏設爲25dp,緣由很少說了

這樣就能夠達成了咱們的目標,若是隻是這樣也就罷了,按照上面作就能夠了,關鍵是本菜是喜歡緊跟潮流的,使用MD風格的DrawerLayout+NavigationView時,在android4.4的手機下,就會變這樣了:


android4.4上的效果


很明顯,drawerlayout並沒用被擴展至系統狀態欄,但在android5.0以上效果仍是能夠的,這讓我很奇怪,只能歸咎於5.0的優化了


android5.0上的效果


通過各類折騰終於想起來,能夠把fitsSystemWindows的特性用在drawerlayout上試試,最後發現竟然能夠,最終將設置windowTranslucentStatus的代碼調整以下:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes(); local LayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags); if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){ //將側邊欄頂部延伸至status bar mDrawerLayout.setFitsSystemWindows(true); //將主頁面頂部延伸至status bar;雖默認爲false,但經測試,DrawerLayout需顯示設置 mDrawerLayout.setClipToPadding(false); } }

最終android4.4上也能夠顯示正常:


android4.4上修正後的效果

2. 不使用toolbar的解決方案

不使用toolbar時,而是actionbar時,由於actionbar很差定製,因此沒法採用上面那個方法,只能採用其它方法,這裏的方案主要參考這裏:Translucent System Bar 的最佳實踐
這篇簡書看的本菜暈乎乎的,仔細看下來,其實都是基於一個原理:
無論有沒有actionbar,內容佈局的背景顏色一概設爲主題顏色,而後有actionbar的話,就將actionbar與內容佈局的背景顏色同時設爲主題顏色,而後,每一個內容佈局的根佈局都要設上fitsSystemWindows="true"進行調整,感受超麻煩有沒有?


不說多少,簡述步驟:

  1. 在代碼中設置透明化,步驟同上
  2. 設置內容佈局的根佈局的背景顏色爲主題顏色,同時設置fitsSystemWindows="true"
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorPrimary" android:fitsSystemWindows="true" android:orientation="vertical">
  3. 在內容佈局的下面再設置一層內容佈局,設背景顏色爲白色(或其它顏色):
    <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/c_light_white" android:gravity="center" android:orientation="vertical">

至此,這種方案也完成了,看下效果:


android4.4上的效果

能夠看出,這種方案通常狀況下,仍是可行的,可是有三個問題:

  1. 若是用上drawerlayout+navigationview,actionbar就會覆蓋在側邊欄上(如上圖),暫時未找到解決方案,可是我想說你都用drawerlayout+navigationview了,爲什麼不用toolbar,所以這個問題應該不是問題,何況還可使用其它的側邊欄實現方式,各位道友能夠試試
  2. 這種方案在每一個根佈局上都要設fitsSystemWindows="true"進行調整,固然上面也有優化方案,可仍然以爲很麻煩,
  3. 每一個根佈局裏都要多加的一層佈局來覆蓋根佈局的背景主題顏色

所以,這種方案的確不是上上之選.

總結

本文主要在考慮使用標題欄(actionbar/toolbar)的狀況下,作出的方案,固然你也能夠自定義標題欄,或者不使用標題欄;其實均可以基於上面同樣的道理:

在狀態欄透明化的前提下,調整頂部view的padding-top,來達到狀態欄自適應一體化的目的

網上還有其它蠻多的解決方案,如:

  1. 使用開源庫SystemBarTint,這個庫也挺不錯的,能夠動態改變系統狀態欄顏色,可是做者已經2年沒有維護了,如今技術更新迭代這麼快,鬼知道這個庫會不會出現什麼問題,所以能夠放棄使用了
  2. 若是不怕麻煩,還能夠new一個高度和狀態欄同樣高的view,插入到內容佈局的上面,可是,想一想都以爲麻煩,我也懶得試了
相關文章
相關標籤/搜索