來自我的CSDN博客:http://blog.csdn.net/dahaohan/article/details/52175190
看過Android的桌面應(yīng)用都是介樣的:
如何讓自己的應(yīng)用也達(dá)到這般效果呢每聪?這里就介紹幾種常用的方法以及它們之間的區(qū)別琳骡。
首先展示下此次demo的布局和初始狀態(tài):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.jokerlee.androidlsample.MainActivity"
android:background="@android:color/holo_green_dark"
android:fitsSystemWindows="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="Hello World."/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="Hello World."/>
</RelativeLayout>
初始效果圖如下:
透明狀態(tài)欄/導(dǎo)航欄##
使用這個(gè)方式首先要理解幾個(gè)概念,窗口層級以及窗口background/窗口透明:
Google在API-19 以及API-21新增對狀態(tài)欄/導(dǎo)航欄窗口透明和顏色的控制:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
getWindow().setStatusBarColor(blackColor);
getWindow().setNavigationBarColor(blackColor);
對應(yīng)的在主題內(nèi)即可控制:
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
這里首先要明了這里狀態(tài)欄和導(dǎo)航欄窗口是系統(tǒng)級窗口而Activity對應(yīng)的時(shí)應(yīng)用窗口妙痹,它們屬于不同的窗口層級吉懊;
然后狀態(tài)欄/導(dǎo)航欄系統(tǒng)級窗口是在App應(yīng)用窗口之上庐橙,故而Activity應(yīng)用窗口雖然有整個(gè)屏幕的大小,但是可顯示內(nèi)容的區(qū)域得除去其上疊加的不透明的窗口區(qū)域借嗽。詳細(xì)的窗口計(jì)算繪制可參考大神老羅的博文:
Android窗口管理服務(wù)WindowManagerService計(jì)算Activity窗口大小的過程分析
下面來使用主題控制導(dǎo)航欄/狀態(tài)欄透明怕午,同時(shí)看看上述兩種設(shè)置透明的方式效果有何不同:
<style name="TestTheme" parent="android:Theme.Material.NoActionBar">
<!--下列兩行控制使得應(yīng)用窗口透明,用于展示一些差異-->
<item name="android:windowBackground">@color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<!--設(shè)置導(dǎo)航欄/狀態(tài)欄窗口color為透明-->
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<!--<item name="android:windowTranslucentStatus">true</item>-->
<!--<item name="android:windowTranslucentNavigation">true</item>-->
</style>
初始桌面和啟動Activity效果圖:
可以看到雖然導(dǎo)航欄/狀態(tài)欄透明了淹魄,當(dāng)時(shí)應(yīng)用窗口顯示的內(nèi)容依然只是除去了兩個(gè)系統(tǒng)窗口之外的區(qū)域郁惜,并沒有衍生到導(dǎo)航欄/狀態(tài)欄之下。
//若是使用window flag控制導(dǎo)航欄/狀態(tài)欄透明
<style name="TestTheme" parent="android:Theme.Material.NoActionBar">
<!--下列兩行控制使得應(yīng)用窗口透明甲锡,用于展示一些差異-->
<item name="android:windowBackground">@color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<!--設(shè)置導(dǎo)航欄/狀態(tài)欄窗口color為透明-->
<!--<item name="android:statusBarColor">@android:color/transparent</item>-->
<!--<item name="android:navigationBarColor">@android:color/transparent</item>-->
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
效果如下:
可以看到已經(jīng)將應(yīng)用的內(nèi)容布局延伸到導(dǎo)航欄/狀態(tài)欄下方了兆蕉,來看看關(guān)于android:windowTranslucentStatus
android:windowTranslucentNavigation的官方說明看看來理解其與設(shè)置color transparent的區(qū)別:
/**
* Window flag: request a translucent status bar with minimal system-provided
* background protection.
*
* <p>This flag can be controlled in your theme through the
* {@link android.R.attr#windowTranslucentStatus} attribute; this attribute
* is automatically set for you in the standard translucent decor themes
* such as
* {@link android.R.style#Theme_Holo_NoActionBar_TranslucentDecor},
* {@link android.R.style#Theme_Holo_Light_NoActionBar_TranslucentDecor},
* {@link android.R.style#Theme_DeviceDefault_NoActionBar_TranslucentDecor}, and
* {@link android.R.style#Theme_DeviceDefault_Light_NoActionBar_TranslucentDecor}.</p>
*
* <p>When this flag is enabled for a window, it automatically sets
* the system UI visibility flags {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and
* {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.</p>
*/
public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000;
* <p>When this flag is enabled for a window, it automatically sets
* the system UI visibility flags {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and
* {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.</p>
*/
public static final int FLAG_TRANSLUCENT_NAVIGATION = 0x08000000;
根據(jù)FLAG的說明,可以看出設(shè)置該標(biāo)志位等同于View申請?jiān)O(shè)置:
//使得布局延伸到狀態(tài)欄和導(dǎo)航欄區(qū)域
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
//透明狀態(tài)欄/導(dǎo)航欄
window.setStatusBarColor(Color.TRANSPARENT);
window.setNavigationBarColor(Color.TRANSPARENT);
//這樣的效果跟上述的主題設(shè)置效果類似
PS:從效果圖看缤沦,雖然布局延伸到狀態(tài)欄導(dǎo)航欄區(qū)域虎韵,但是相應(yīng)的內(nèi)容“hello world”文字也被狀態(tài)欄/導(dǎo)航欄遮住了。在布局根視圖設(shè)置fitsSystemWindows為true可以使得缸废,系統(tǒng)自動為視圖添加一個(gè)狀態(tài)欄/導(dǎo)航欄高度的padding:
rootView.setFitsSystemWindows(true);
//或者xml view標(biāo)簽加入
android:fitsSystemWindows="true"
效果如下:
查看SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 和 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN的說明包蓝,可以發(fā)現(xiàn)其實(shí)還有兩個(gè)非常接近的FLAG:
public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
//這兩flag跟上述主要區(qū)別在于驶社,在設(shè)置和取消flag時(shí),會引起重新布局测萎,也就是當(dāng)從SYSTEM_UI_FLAG_FULLSCREEN模式
//退出時(shí)亡电,activity的內(nèi)容顯示窗口會變小,看起來就是這個(gè)布局內(nèi)容畫面會上移/下移硅瞧。
根據(jù)官方的說明提示份乒,SYSTEM_UI_FLAG_FULLSCREEN / SYSTEM_UI_FLAG_HIDE_NAVIGATION主要用于動態(tài)切換隱藏/顯示系統(tǒng)導(dǎo)航欄/狀態(tài)欄;例如書籍閱讀應(yīng)用/視頻播放應(yīng)用等腕唧。而像游戲類的全屏應(yīng)用則推薦使用window flag或辖。
API-19以下的如何實(shí)現(xiàn)?
上述的透明導(dǎo)航欄/狀態(tài)欄等API基本是需要API-19或是API-21才能使用的枣接,這里還有一種API-1的方案能夠?qū)崿F(xiàn)布局內(nèi)容全屏:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
實(shí)際上只需要設(shè)置FLAG_LAYOUT_NO_LIMITS就足夠了颂暇;這FLAG是看Android原生的Launcher / Keyguard源碼,看到有用到如此設(shè)置但惶,其窗口設(shè)置具體原理我也沒有弄清..... 有大神了解可以指點(diǎn)下蟀架。
PS:這個(gè)套路下,使用fitsSystemWindows="true"是無效的榆骚,智能自己控制號布局位置片拍。