//DecorView获取
Activity.getWindow().getDecorView()
//DecorView获取contentView
Activity.findViewById(android.R.id.content)
//获取activity的 setContentView(int LayoutXml);//即我们xml里面写的xml布局
ViewGroup rootView = (ViewGroup) content.getChildAt(0);
全屏化一般用在启动页:
参考:http://blog.csdn.net/lu_ca/article/details/72778694
requestWindowFeature(Window.FEATURE_NO_TITLE);// 隐藏标题
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏
setContentView(R.layout.activity_main);
注意:setContentView一定要写在设置全屏后边
沉浸式的一般套路
在Android上,关于对StatusBar(状态栏)的操作,一直都在不断改善,并且表现越来越好,在Android4.4 以下,我们可以对StatusBar和 NavigationBar进行显示和隐藏操作。但是直到Android4.4,我们才能真正意义上的实现沉浸式状态栏。从Android4.4 到现在(Android 7.1),关于沉浸式大概可以分成三个阶段:
-
Android4.4(API 19) - Android 5.0(API 21): 这个阶段可以实现沉浸式,但是表现得还不是很好,实现方式为: 通过
FLAG_TRANSLUCENT_STATUS
设置状态栏为透明并且为全屏模式,这个时候布局会入侵状态栏,我们可以通过添加一个与StatusBar 一样大小的View,将View 的 background 设置为我们想要的颜色,从而来实现沉浸式。 -
Android 5.0(API 21)以上版本: 在Android 5.0的时候,加入了一个重要的属性和方法 android:statusBarColor (对应方法为 setStatusBarColor),通过这个方法我们就可以轻松实现沉浸式。也就是说,从Android5.0开始,系统才真正的支持沉浸式。
-
Android 6.0(API 23)以上版本:其实Android6.0以上的实现方式和Android 5.0 +是一样,为什么要将它归为一个单独重要的阶段呢?是因为从Android 6.0(API 23)开始,我们可以改状态栏的绘制模式,
SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
可以显示白色或浅黑色的内容和图标(除了魅族手机,魅族自家有做源码更改,6.0以下就能实现)
-
代码未行,效果先上
-
Android4.4(API 19) - Android 5.0(API 21)如何实现
在 [KITKAT][null-link] 之后,Android Window支持了一些新的属性,4.4以上能设置沉浸状态栏,正是因为下面的flag引入了,通过这两个flag可以设置Status Bar或Nav Bar透明。设置这个属性不做其他操作一定会入侵状态栏
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
和 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCRE
这两个flag会被自动添加到system UI visibility中。
正如它们的变量名的意思,使用这两个属性,可以使得状态栏和导航栏变为透明,导航栏指的就是Android下方的三大按键,当然只使用第一个属性也可以达到今天所要完成的效果。下面的示例代码将使状态栏和导航栏变得透明
我们注意到上面的flag名为TRANSLUCENT,而不是TRANSPARENT, 知乎 指出了,TranslucentStatus 在 4.4 和 5.x 上表现不同,4.4 是一层渐变的遮罩层,5.x 以上是一条半透明的遮罩层(5.0以上不建议用这个方法,下面有详解),比如Genymotion模拟器上就是这样,但在一些其他机器比如小米上,就是全透明的,这应该是和系统有关的。
Genymotion模拟器4.4上透明状态栏的效果:
小米4.4上透明状态栏的效果:
image.png
Genymotion模拟器5.x上透明状态栏的效果:
image.png
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initWindow();
}
@TargetApi(19)
private void initWindow(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
直接运行之后,状态栏直接透明了,但是并不是我们想要的效果。当设置Status Bar透明后,由于visibility flag的自动添加,屏幕会变成全屏的。所以这时候ToolBar就直接跑到StatusBar下面了,如图:
image.png这个问题也很好解决,在 style theme 添加,或者Activity的layout的属性android:fitsSystemWindows="true",但是发现,StatusBar变灰色了。(那是xml里面主布局的颜色,因为fitsSystemWindows是设置padding的,其实只需要把xml主布局颜色设置了就不会变灰了)
image.png小结:
Android4.4上实现沉浸式状态栏的套路是:为window添加FLAG_TRANSLUCENT_STATUS Flag
- 方法1.往DecorView添加一个和status bar 一样大小的View 站位,然后添加setFitsSystemWindows从而让让标题栏不会与status bar 重叠。(因为DecorView是framlayout即使加View也不行把contenView顶下来,所以contenView增加setFitsSystemWindows属性会自定增加status bar的高度)即上面演示的代码。
- 方法2.不加VIew,直接手动设置xml里面的主布局padding属性为statusView的高度。(不要设置margin会出现状态栏变成灰色)
- 方法3.最简单,直接设置setFitsSystemWindows后,设置主布局颜色为标题栏颜色就可以了。但是这样的做法不能解决图片问题沉浸式问题。
- 若:而图片延伸到状态栏只需要设置FLAG_TRANSLUCENT_STATUS就OK
ps:
android:clipChildren:clipChildren表示是否限制子View在其范围内,默认true
android:clipToPadding:ClipToPadding用来定义ViewGroup是否允许在padding中绘制。默认情况下,cliptopadding被设置为ture, 也就是把padding中的值都进行裁切了,如图片超出边界后被裁剪。默认true
-
2.2 Android 5.0(API 21)以上实现沉浸式的方式
google 加入了一个比较重要的方法setStatusBarColor (对应属性:android:statusBarColor)
注意:想要这个方法生效,必须还要配合一个Flag一起使用,必须设置FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
,并且不能设置FLAG_TRANSLUCENT_STATUS
(Android 4.4才用这个)
ps:如果绘制的时候不清除这个flag或者加进去,View.SYSTEM_UI_FLAG_LAYOUT_STABLE的话,实现statusBar绘制了同时,自己的View也会入侵
这个flag 也是在Android 5.0添加的,它的作用是什么呢?
解释:设置了FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,表明会Window负责系统bar的background 绘制,绘制透明背景的系统bar(状态栏和导航栏),然后用getStatusBarColor()和getNavigationBarColor()的颜色填充相应的区域。这就是Android 5.0 以上实现沉浸式导航栏的原理。
实现沉浸式添加如下代码:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
//注意要清除 FLAG_TRANSLUCENT_STATUS flag
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().setStatusBarColor(getResources().getColor(android.R.color.holo_red_light));
Android 5.0图片延伸到状态栏只需设置windowTranslucentStatus,将 statusBarColor 设置为透明即可:就是相当于没有清除FLAG_TRANSLUCENT_STATUS,所以xml入侵了
<style name="ImageTranslucentTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowTranslucentStatus">true</item>
<!-- 设置statusBarColor 为透明-->
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
tip
在Android 5.0 之后我们除了可以在代码中改变状态栏的颜色,还可以在XML中设置主题色,这种方式我们的App不属于沉浸式,在状态栏的下面
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item> <!-- toolbar -->
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> <!-- 状态栏 -->
<item name="colorAccent">@color/colorAccent</item> <!-- 页面中常用控件默认颜色 -->
<item name="android:windowBackground">@color/bg_f6</item><!--window背景-->
</style>
image.png
注意:FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,表明会Window负责系统bar的background 绘制(得先清除4.4的flag),所以不需要设置fitsSystemWindows或者手动设置一个和statusBar一样的大小的View,但是想实现图片沉浸式,要设置windowTranslucentStatus
2.3 Android 6.0 + 实现状态栏字色和图标浅黑色
使用沉浸式的时候会遇到一个问题,那就是Android 系统状态栏的字色和图标颜色为白色,当我的主题色或者图片接近白色或者为浅色的时候,状态栏上的内容就看不清了。 ,这个问题在Android 6.0的时候得到了解决。Android 6.0 新添加了一个属性SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
解释:为setSystemUiVisibility(int)方法添加的Flag,请求status bar 绘制模式,它可以兼容亮色背景的status bar 。要在设置了FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag ,同时清除了FLAG_TRANSLUCENT_STATUS flag 才会生效。
代码:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
除了在代码中添加以外,还可以直接在主题中使用属性:
<style name="MDTheme" parent="Theme.Design.Light.NoActionBar">
//为了防止冲突取消4.4的透明
<item name="android:windowTranslucentStatus">false</item>
//设置5.0的沉浸式
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
// 设置沉浸式烟色
<item name="android:statusBarColor">@android:color/holo_red_light</item>
<!-- Android 6.0以上 状态栏字色和图标为浅黑色-->
<item name="android:windowLightStatusBar">true</item>
<!-- <item name="android:windowTranslucentStatus">true</item> --> <!-- 适用4.4到5.0的系统-->
</style>
好了说到这里:如何统一4.4和5.0的沉浸式呢?
个人认为方法有几个方法:
法一:设置 fitsSystemWindows 属性
这样既能解决标题栏入侵状态栏问题,和输入法弹出问题
在 style theme 添加,或者Activity的layout的属性android:fitsSystemWindows="true"!
属性解释:在沉浸式的情况下,如果某个View 的fitsSystemWindows 设为true,那么该View的padding属性将由系统设置,用户在布局文件中设置的padding会被忽略。系统会为该View设置一个paddingTop,值为statusbar的高度。fitsSystemWindows默认为false
参考:https://www.jianshu.com/p/5cc3bd23be7b
设置前这个属性之前是这样的的:
但是设置完之后就变成,顶部变白色(其实那是根布局的颜色)
image.png
解决方法一:根布局设置为标题所需要的颜色
解决方法二:自己在decoView绘制一个和状态栏大小一样,颜色和标题栏一样的View!具体步骤!
解决:自己添加一个带颜色和状态栏一样高的矩形的View
/**
* 生成一个和状态栏大小相同的矩形条
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
* @return 状态栏矩形条
*/
private static View createStatusView(Activity activity, int color) {
// 获得状态栏高度
int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
int statusBarHeight = activity.getResources().getDimensionPixelSize(resourceId);
// 绘制一个和状态栏一样高的矩形
View statusView = new View(activity);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
statusBarHeight);
statusView.setLayoutParams(params);
statusView.setBackgroundColor(color);
return statusView;
}
整体代码:
/**
* 设置状态栏颜色
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
*/
public static void setColor(Activity activity, int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 设置状态栏透明
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// 生成一个状态栏大小的矩形
View statusView = createStatusView(activity, color);
// 添加 statusView 到布局中
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
decorView.addView(statusView);
// 设置根布局的参数
ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
rootView.setFitsSystemWindows(true);
rootView.setClipToPadding(true);
}
}
在 setContentView() 之后调用 setColor(Activity activity, int color) 方法即可。
法二:设置手动设置标题栏的paddingTop
这可以实现titlebar整体文字不入侵状态栏,ImageView整体浸入入侵状态栏,但是得手动解决输入法问题(5.0以后的不要清除FLAG_TRANSLUCENT_STATUS )
/**
* 通过设置全屏,设置状态栏透明
*
* @param activity
*/
private void fullScreen(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色
Window window = activity.getWindow();
View decorView = window.getDecorView();
//两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
//导航栏颜色也可以正常设置
// window.setNavigationBarColor(Color.TRANSPARENT);
} else {
Window window = activity.getWindow();
WindowManager.LayoutParams attributes = window.getAttributes();
int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
attributes.flags |= flagTranslucentStatus;
// attributes.flags |= flagTranslucentNavigation;
window.setAttributes(attributes);
}
}
}
public void setTitleBarPadding(final Activity activity, final View viewPadding) {
if (viewPadding != null) {
Object haveSetOffset = viewPadding.getTag(TAG_KEY_HAVE_SET_OFFSET);
if (haveSetOffset != null && (Boolean) haveSetOffset) {
return;
}
viewPadding.setPadding(viewPadding.getPaddingLeft(), viewPadding.getPaddingTop() + getStatusBarHeight(activity),
viewPadding.getPaddingRight(), viewPadding.getPaddingBottom());
viewPadding.setTag(TAG_KEY_HAVE_SET_OFFSET, true);
}
}
在 setContentView() 之后调用 fullScreen() 和setTitleBarPadding()方法即可。
法三:直接在标题栏里面设置一个跟状态栏一样大小的View。
得到的效果与2类似。
解决输入法与沉浸式冲突:https://blog.csdn.net/smileiam/article/details/69055963
推荐库:https://github.com/gyf-dev/ImmersionBar
推荐工具类:https://github.com/laobie/StatusBarUtil
网友评论