自己在使用手機的過程中都會看到其他app的透明狀態欄(或者國內成為沉浸式狀態欄),再看看自己app上放系統通知欄黑黑的一塊,突兀又不和諧,就想著把自己的app也弄得比較炫一些。
言歸正傳,下面記錄下操作步驟和可能有坑的點,歡迎指正~
1. 5.0系統以上
2. BaseActivity中加入
Window window = getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
//先將狀態欄調整為透明
window.setStatusBarColor(Color.TRANSPARENT);
是不是看到那么多的FLAG_XXX
心都累了,這些累人的FLAG_XXX
我們先按下不表,我們直接來看下最后一行。
各位看官可能要說了,最后一行那么簡單,不就是設置個狀態欄顏色唄,整段代碼可能就這行看得最清晰了。
嗯,單純從代碼的角度,這行是最清晰不過的了,但是前面的這些累人的FLAG_XXX
可都跟這行的代碼有著密切的關系。讓我們直接進入這個方法中查看下
/**
* Sets the color of the status bar to {@code color}.
*
* For this to take effect,
* the window must be drawing the system bar backgrounds with
* {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} and
* {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS} must not be set.
*
* If {@code color} is not opaque, consider setting
* {@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and
* {@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
* <p>
* The transitionName for the view background will be "android:status:background".
* </p>
*/
public abstract void setStatusBarColor(@ColorInt int color);
仔細把注釋看完,是不是就明白那些FLAG_XXX
到底是為什么需要那樣設置了。
簡單來說,這個setStatusBarColor(@ColorInt int color)
方法要求我們的window
- 必須沒有
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
這是第二行代碼window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
的由來 - 必須有
WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
這則是第四行代碼window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
的由來。
然后,當你需要的是非透明顏色的狀態欄時,需要設置兩個標志
分別是View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
與View.SYSTEM_UI_FLAG_LAYOUT_STABLE
,這樣就搞清楚了代碼第三行所做的工作
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
3. 根據app的主色調去調整狀態欄的顏色(對于有actionBar之類的界面)
有眼尖的小伙伴們應該已經發現我們之前的代碼上設置狀態欄的顏色是透明,這沒有達到我們需要的效果啊,我們需要的是跟app主色調相同的那個顏色,我當然也知道這點,可是為什么要先設置成透明的呢,這是因為考慮到有些界面我們會設置為全屏,不顯示系統通知欄,這時就要區分這兩種情況了。再根據自己的需求來設置顏色。
如果沒有這方面的需求,直接在上一步設置需要的顏色就可以了。
4. fitsSystemWindows方法
其實到第三步做完,我們已經能看到通知欄變成了我們所想要的顏色,效果如下圖
看起來已經搞定了啊,還需要做些什么呢。那是因為我們的ContentView中只有一個TextView,所以并不能很清楚地展示效果是如何,接下來,改造下ContentView再來觀察下效果
這次應該比較直觀能看到問題所在了,我們的ContentView的區域被系統通知欄遮住了一塊。
這需要我們在每個頁面的根布局中加入以下這句話
android:fitsSystemWindows="true"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
不過每個頁面加這個很麻煩,也可以全局的style中加入
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:fitsSystemWindows">true</item>
</style>
這時再來看下效果
已經沒有遮擋了,這時才算真的大功告成。
5. 坑
效果達成了,難免會遇到一些坑,下面我記錄下我遇到的幾個問題點
- 有些界面需要全屏展示
上文說到的第三步,其實在實際運用中我是去判斷是否有自定義的ActionBar存在,有則使用app主色調,沒有則是第一步中的Transparent,所以在沒有自定義ActionBar的界面會變成灰色的狀態欄,解決方案是在這些特殊的界面全屏,我的做法是使用theme來達到全屏的效果
android:theme="@android:style/Theme.Light.NoTitleBar"
- Toast顯示不正常問題
這個應該是Toast也被fitsSystemWindows限制的問題,解決方法是我們showToast的時候傳入的是個系統上下文
context ------------> context.getApplicationContext()
- 自定義View顯示不正常問題
如一部分view缺失等問題,這時需要把自定義view在代碼或者xml中設置android:fitsSystemWindows="false"
setFitsSystemWindows(false);
或者
//第7行
<me.roadley.ui.VerticalTextView
android:id="@+id/some_tv"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/some_color"
android:fitsSystemWindows="false"
app:text="@string/some_string"
app:textColor="@color/white"
app:textSize="14sp"
android:layout_centerVertical="true"/>
后記
5.0開始,Google推出Material Design,使用Theme.Material(MD主題)或Theme.AppCompat主題并至少設置ColorPrimaryDark屬性就可以實現status bar半透明效果。
不過我們的項目并沒有使用AppCompat主題,而且個人覺得與自己的ActionBar相同的顏色這種感覺會比較好哈~