來自我的CSDN博客:http://blog.csdn.net/dahaohan/article/details/52175190
看過Android的桌面應用都是介樣的:
如何讓自己的應用也達到這般效果呢?這里就介紹幾種常用的方法以及它們之間的區別。
首先展示下此次demo的布局和初始狀態:
<?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>
初始效果圖如下:
透明狀態欄/導航欄##
使用這個方式首先要理解幾個概念,窗口層級以及窗口background/窗口透明:
Google在API-19 以及API-21新增對狀態欄/導航欄窗口透明和顏色的控制:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
getWindow().setStatusBarColor(blackColor);
getWindow().setNavigationBarColor(blackColor);
對應的在主題內即可控制:
<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>
這里首先要明了這里狀態欄和導航欄窗口是系統級窗口而Activity對應的時應用窗口,它們屬于不同的窗口層級;
然后狀態欄/導航欄系統級窗口是在App應用窗口之上,故而Activity應用窗口雖然有整個屏幕的大小,但是可顯示內容的區域得除去其上疊加的不透明的窗口區域。詳細的窗口計算繪制可參考大神老羅的博文:
Android窗口管理服務WindowManagerService計算Activity窗口大小的過程分析
下面來使用主題控制導航欄/狀態欄透明,同時看看上述兩種設置透明的方式效果有何不同:
<style name="TestTheme" parent="android:Theme.Material.NoActionBar">
<!--下列兩行控制使得應用窗口透明,用于展示一些差異-->
<item name="android:windowBackground">@color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<!--設置導航欄/狀態欄窗口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效果圖:
可以看到雖然導航欄/狀態欄透明了,當時應用窗口顯示的內容依然只是除去了兩個系統窗口之外的區域,并沒有衍生到導航欄/狀態欄之下。
//若是使用window flag控制導航欄/狀態欄透明
<style name="TestTheme" parent="android:Theme.Material.NoActionBar">
<!--下列兩行控制使得應用窗口透明,用于展示一些差異-->
<item name="android:windowBackground">@color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<!--設置導航欄/狀態欄窗口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>
效果如下:
可以看到已經將應用的內容布局延伸到導航欄/狀態欄下方了,來看看關于android:windowTranslucentStatus
android:windowTranslucentNavigation的官方說明看看來理解其與設置color transparent的區別:
/**
* 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;
根據FLAG的說明,可以看出設置該標志位等同于View申請設置:
//使得布局延伸到狀態欄和導航欄區域
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
//透明狀態欄/導航欄
window.setStatusBarColor(Color.TRANSPARENT);
window.setNavigationBarColor(Color.TRANSPARENT);
//這樣的效果跟上述的主題設置效果類似
PS:從效果圖看,雖然布局延伸到狀態欄導航欄區域,但是相應的內容“hello world”文字也被狀態欄/導航欄遮住了。在布局根視圖設置fitsSystemWindows為true可以使得,系統自動為視圖添加一個狀態欄/導航欄高度的padding:
rootView.setFitsSystemWindows(true);
//或者xml view標簽加入
android:fitsSystemWindows="true"
效果如下:
查看SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 和 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN的說明,可以發現其實還有兩個非常接近的FLAG:
public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
//這兩flag跟上述主要區別在于,在設置和取消flag時,會引起重新布局,也就是當從SYSTEM_UI_FLAG_FULLSCREEN模式
//退出時,activity的內容顯示窗口會變小,看起來就是這個布局內容畫面會上移/下移。
根據官方的說明提示,SYSTEM_UI_FLAG_FULLSCREEN / SYSTEM_UI_FLAG_HIDE_NAVIGATION主要用于動態切換隱藏/顯示系統導航欄/狀態欄;例如書籍閱讀應用/視頻播放應用等。而像游戲類的全屏應用則推薦使用window flag。
API-19以下的如何實現?
上述的透明導航欄/狀態欄等API基本是需要API-19或是API-21才能使用的,這里還有一種API-1的方案能夠實現布局內容全屏:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
實際上只需要設置FLAG_LAYOUT_NO_LIMITS就足夠了;這FLAG是看Android原生的Launcher / Keyguard源碼,看到有用到如此設置,其窗口設置具體原理我也沒有弄清..... 有大神了解可以指點下。
PS:這個套路下,使用fitsSystemWindows="true"是無效的,智能自己控制號布局位置。