来自我的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"是无效的,智能自己控制号布局位置。