Android 沉浸式

18年12月17日 所在的这家公司 让我讲一堂 分享课。

然后我就在想 讲点什么好呢,然后网上搜了一下 感觉讲点歪门邪道,

然后对项目中应用也比较多的沉浸式进行一下分享吧!

ok 废话少说 开始了~!

沉浸式状态栏简介
 

在Android上,关于对StatusBar(状态栏)的操作,一直都在不断改善,并且表现越来越好,在Android4.4 以下,我们可以对StatusBar和 NavigationBar进行显示和隐藏操作。但是直到Android4.4,我们才能真正意义上的实现沉浸式状态栏。从Android4.4 到Android 7.1,关于沉浸式大概可以分成三个阶段:

Android4.4(API 19) - Android 5.0(API 21): 1

这个阶段可以实现沉浸式,但是表现得还不是很好,实现方式为: 通过FLAG_TRANSLUCENT_STATUS设置状态栏为透明并且为全屏模式,然后通过添加一个与StatusBar 一样大小的View,将View 的 background 设置为我们想要的颜色,从而来实现沉浸式。

Android 5.0(API 21)以上版本: 2

在Android 5.0的时候,加入了一个重要的属性和方法 android:statusBarColor (对应方法为 setStatusBarColor),通过这个方法我们就可以轻松实现沉浸式。也就是说,从Android5.0开始,系统才真正的支持沉浸式。

Android 6.0(API 23)以上版本:3

其实Android6.0以上的实现方式和Android 5.0 +是一样,为什么要将它归为一个单独重要的阶段呢?是因为从Android 6.0(API 23)开始,我们可以改状态栏的绘制模式,可以显示白色或浅黑色的内容和图标

 

第1阶段:

源码:

Android4.4(API 19) - Android 5.0(API 21)实现沉浸式的方式 源码:

/**  
* 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;

在Android 4.4 新增了一个重要的属性:FLAG_TRANSLUCENT_STATUS

解释:设置状态栏透明,并且变为全屏模式。

上面的解释已经说得很清楚了,当window的这个属性有效的时候,会自动设置 systemUiVisibility的标志SYSTEM_UI_FLAG_LAYOUT_STABLE     和     SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN  。

有两种方式实现这个属性: 可以在代码中设置,如下:

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 

当然也可以在theme 中设置属性windowTranslucentStatus,如下:

android:windowTranslucentStatus 

效果图 

效果如图,可以看出,沉浸式的效果是出来了,但是也有一个问题,

我们的标题栏和状态栏重叠了,相当于整个布局上移了StatusBar 的高度。

为了让标题栏回到原来的位置,

我们在标题栏的上方添加一个大小和StatusBar大小一样的View,

View 的BackgroundColor 为标题栏一样的颜色,这个View起到一个占位的作用。

这个时候,标题栏就会下移StatusBar的高度,回到正常的位置。

如果是一张图片延伸到状态栏的话,直接设置FLAG_TRANSLUCENT_STATUS就可以了

Android4.4上实现沉浸式状态栏的套路

为window添加FLAG_TRANSLUCENT_STATUS Flag,然后添加一个和status bar 一样大小的View 站位,

从而让让标题栏不会与status bar 重叠。

而图片延伸到状态栏只需要设置FLAG_TRANSLUCENT_STATUS就OK。

前面说过,沉浸式在Android4.4 - Android5.0 之间的版本表现得不是很好,

状态栏的顶部有一个渐变,会显示出黑色的阴影(底部的导航栏也是一样的效果),

在Android 5.0 版本已经被修复了。

第2-3阶段:

Android 5.0 是一个里程碑式的版本,从Android 5.0开始,

Google 推出了全新的设计规范 Material Design,并且原生控件就可以实现一些炫酷的UI动效。

从这个版本开始,google 加入了一个比较重要的方法setStatusBarColor

(对应属性:android:statusBarColor),通过这个方法,

可以很轻松地实现沉浸式状态栏。方法如下:

/**
 * 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一起使用,

必须设置FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS ,

并且不能设置FLAG_TRANSLUCENT_STATUS(Android 4.4才用这个)

我们来看一下FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS这个flag:

可以看到,这个flag 也是在Android 5.0添加的,它的作用是什么呢?

解释:设置了FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,

表明Window负责系统bar的background 绘制,绘制透明背景的系统bar(状态栏和导航栏),

然后用getStatusBarColor()和getNavigationBarColor()的颜色填充相应的区域。

这就是Android 5.0 以上实现沉浸式导航栏的原理。

//需要设置这个 flag 才能调用 setStatusBarColor 来设置状态栏颜色 window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 

//设置状态栏颜色
window.setStatusBarColor(statusColor);

沉浸式状态栏 分为两种:

一、沉浸式全屏模式 Immersive full-screen mode(官方的一段话。)

To provide your app with a layout that fills the entire screen, the new SYSTEM_UI_FLAG_IMMERSIVE flag for setSystemUiVisibility()(when combined with SYSTEM_UI_FLAG_HIDE_NAVIGATION enables a new immersivefull-screen mode. While immersive full-screen mode is enabled, your activity continues to receive all touch events. The user can reveal the system bars with an inward swipe along the region where the system bars normally appear. This clears the SYSTEM_UI_FLAG_HIDE_NAVIGATION flag (and the SYSTEM_UI_FLAG_FULLSCREEN flag, if applied) so the system bars remain visible. However, if you'd like the system bars to hide again after a few moments, you can instead use the SYSTEM_UI_FLAG_IMMERSIVE_STICKY flag.

 谷歌翻译:

沉浸式全屏模式(官方的一段话。) 为了给你的应用程序提供一个填满整个屏幕的布局,setSystemUiVisibility()的新SYSTEM_UI_FLAG_IMMERSIVE标志(当与SYSTEM_UI_FLAG_HIDE_NAVIGATION结合使用时,可启用全新的沉浸式全屏模式。启用沉浸式全屏模式时,您的活动将继续接收所有触摸 用户可以通过沿系统条通常出现的区域向内滑动来显示系统条。这将清除SYSTEM_UI_FLAG_HIDE_NAVIGATION标志(以及SYSTEM_UI_FLAG_FULLSCREEN标志,如果应用),这样系统条仍然可见。但是,如果你是 就像系统栏稍微隐藏一样后,你可以改为使用SYSTEM_UI_FLAG_IMMERSIVE_STICKY标志。

Immersive full-screen mode (沉浸式全屏模式)

Immersive full-screen mode (沉浸式全屏模式) 隐藏status bar(状态栏)使屏幕全屏,

让Activity接收所有的触摸事件。(整个屏幕的)

比如:看电影,玩游戏时就是沉浸式全屏模式  例图如下:?????????

                                                   

沉浸式全屏模式: activity 占据整个屏幕,用户交互时(拖动状态栏所在的位置)才会出现状态栏和导航栏        

本人喜欢玩王者荣耀  就拿荣耀的图片举个例子。

                                交互时 会出现            ????  

                           

二、透明化系统栏 Translucent system bars(官方的一段话。)

You can now make the system bars partially translucent with new themes, Theme.Holo.NoActionBar.TranslucentDecor and Theme.Holo.Light.NoActionBar.TranslucentDecor.By enabling translucent system bars, your layout will fill the area behind the system bars, so you must also enable fitsSystemWindows for the portion of your layout that should not be covered by the system bars. If you're creating a custom theme, set one of these themes as the parent theme or include the windowTranslucentNavigation and windowTranslucentStatus style properties in your theme.

谷歌翻译:

你现在可以使系统栏部分半透明的新主题,Theme.Holo.NoActionBar.TranslucentDecor和Theme.Holo.Light.NoActionBar.TranslucentDecor.By启用半透明系统栏,你的布局将填充系统栏后面的区域,所以你 还必须为layoutSystemWindows启用布局中不应被系统栏覆盖的部分。 如果要创建自定义主题,请将其中一个主题设置为父主题,或在主题中包含windowTranslucentNavigation和windowTranslucentStatus样式属性。

具体意思:

Translucent system bars (透明化系统栏) 使得布局侵入系统栏的后面, 必须启用fitsSystemWindows属性来调整布局才不至于被系统栏覆盖。 另外一种叫“黏性沉浸模式”,让状态栏和虚拟按钮半透明, 应用使用屏幕的全部空间,  当用户从屏幕的上方边沿处向下滑动时,也不会退出该模式,  但是系统界面 (状态栏、 导航栏) 将会以半透明的效果浮现在应用视图之上 , 只有当用户点击系统界面上的控件时, 才会退出黏性沉浸模式。

使用代码实现

Api 19 以上
View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
View.SYSTEM_UI_FLAG_LAYOUT_STABLE                                     API 16
保持整个View稳定, 常和控制System UI悬浮, 隐藏的Flags共用, 
使View不会因为System UI的变化而重新layout。

View.SYSTEM_UI_FLAG_HIDE_NAVIGATION                                   API 14
隐藏导航栏。

View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION                   API 16
视图延伸至导航栏区域,导航栏上浮于视图之上

View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN                           API 16
视图延伸至状态栏区域,状态栏上浮于视图之上。

View.SYSTEM_UI_FLAG_FULLSCREEN                                           API 16
状态栏隐藏,效果同设置WindowManager.LayoutParams.FLAG_FULLSCREEN

然而, 如果你想让系统栏在一段时间后自动隐藏的话,你应该使用SYSTEM_UI_FLAG_IMMERSIVE_STICKY标签。请注意,带有'sticky'的标签不会触发任何的监听器,因为在这个模式下展示的系统栏是处于暂时(transient)的状态。


实体对象的生命周期有三种状态:


      1.Transient(自由状态)
      此时的实体对象和数据库中的记录无关联,只是一个普通的JavaBean。
      2.Persistent(持久状态)
      此时的实体对象和数据库中的记录有关联,其变更将由Hibernate固化到数据库中。该实体对象处于由Hibernate框架所管理的状态。
      3.Detached(游离状态)
      处于Persistent状态的对象,其对应的Session实例关闭之后,那么,此对象就处于"Detached"状态。Detached状态和Transient状态的区别在于Detached状态的对象可以再次与某个Session实例相关联而成为Persistent对象。

Android API Level对应Android版本一览表

导航栏透明

导航栏透明
在values-v19的主题属性中添加一条即可,如下
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

        <item name="windowTranslucentNavigation">true</item>
</style>

效果图

其实我们要设置一个属性,那就是“fitsSystemWindows”,fitsSystemWindows 是在 android 4.4 中引入的。

想了解详细的fitsSystemWindows相关知识请去Google查阅下资料。

在主题属性中添加‘android:fitsSystemWindows’,

如下:

 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">     
   <!-- Customize your theme here. -->     
   <item name="colorPrimary">@color/colorPrimary</item>     
   <item name="colorPrimaryDark">@color/colorPrimaryDark</item>   
   <item name="colorAccent">@color/colorAccent</item>  
   <item name="android:windowTranslucentStatus">true</item>  
   <item name="android:windowTranslucentNavigation">true</item>  
   <item name="android:fitsSystemWindows">true</item>
 </style>

效果圖

Android 5.0

Android5.0状态栏默认颜色是获取我们‘colorPrimaryDark’中的颜色,

如果在主题中没有添加‘colorPrimaryDark’属性则会使用灰色做默认颜色。

在5.0中设置透明的方式和上面一样,我们按照上面方式设置, 默认情况下状态栏和导航栏是灰色半透明的

状态栏全透明 方法如下     

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

        <item name="android:fitsSystemWindows">true</item>
        <!--windowTranslucentStatus 默认就是false -->
        <item name="android:windowTranslucentStatus">false</item>
        <item name="android:windowTranslucentNavigation">true</item>
        <!--@android:color/transparent 是调用系统颜色:透明。-->
        <item name="android:statusBarColor">@android:color/transparent</item>
</style>

差不多就是這些了,後續補充!

©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页