由沉浸式状态栏引出
援引一句郭霖大神的话来破除大家对沉浸式的误解。
其实说到沉浸式状态栏这个名字我也是感到很无奈,真不知道这种叫法是谁先发起的。因为Android官方从来没有给出过沉浸式状态栏这样的命名,只有沉浸式模式(Immersive Mode)这种说法。而有些人在没有完全了解清楚沉浸模式到底是什么东西的情况下,就张冠李戴地认为一些系统提供的状态栏操作就是沉浸式的,并且还起了一个沉浸式状态栏的名字。
所以说真正的沉浸式是什么,还是援引郭霖大神的话:
那么对应到Android操作系统上面,怎样才算是沉浸式体验呢?这个可能在大多数情况下都是用不到的,不过在玩游戏或者看电影的时候就非常重要了。因为游戏或者影视类的应用都希望能让用户完全沉浸在其中,享受它们提供的娱乐内容,但如果这个时候在屏幕的上方还显示一个系统状态栏的话,可能就会让用户分分钟产生跳戏的感觉。
但是我们就是想要我们以前以为的沉浸式的效果,就像Tim和网易云音乐那种效果我们到底要怎么达成呢?我们有两种思路,一个是指定状态栏的颜色,也就是纯色的,还有一种就是通过全屏模式
介绍一下几个属性:
fitsSystemWindows
:
我们的理解是:在Android版本大于5.0的情况下,对于CoordinatorLayout、AppBarLayout、CollapsingToolbarLayout一起使用的时候,如果对其中的一个子控件设置fitsSystemWindows时,需要对它们的父控件都设置该属性;但是对于其它情况,这个属性的含义是为了不让我们的控件占据系统窗口的空间,比如说状态栏和导航栏(这一属性需要设置状态栏或者导航栏透明或者半透明的时候才会有效)。
指定状态栏的颜色来实现沉浸式(这种说法不准确,但是还是暂时这么说)
在style.xml
里面设置对应的Activity
的theme
,通过设置android:statusBarColor
这一属性来直接设置状态栏的颜色,这种方案适用于==纯色==的toolBar
或者ActionBar
,具体代码如下:
1 | <style name="MainActivityTheme" parent="AppTheme"> |
在AndroidManifest.xml
中设置刚才定义的style
,具体的代码如下:
1 | <activity android:name=".MainActivity" |
通过设置全屏和状态栏透明来实现沉浸式
我们首先在需要设置全屏,保持状态栏悬浮,具体的代码如下:
1 | View view = getWindow().getDecorView(); |
接着我们设置状态栏,具体的代码如下:
1 | getWindow().setStatusBarColor(Color.TRANSPARENT); |
通过设置全屏和设置状态栏为TRANSLUCENT
来实现沉浸式
首先也要设置全屏,和之前的一样,接着要设置状态栏透明(在5.0以上为半透明)
1 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); |
Toolbar——Actionbar的替代者
一个Toolbar
的基本效果如下图所示:
我们通常会设置Toolbar
的navigationicon
、subtitle
、title
、menu
和logo
,设置这些属相的代码我贴在下面了:
1 | <android.support.v7.widget.Toolbar |
因为我们指定的style
为Light
,所以文字会变成深色,这会很难看的,这里我们需要把Actionbar
的theme
设置为深色,这样文字就会变成浅色,但是这样弹出的菜单项会变成深色,所以我们又需要设置弹出菜单的theme
。xmlns:app
是因为Material Design
库在Android 5.0系统中才出现,在之前的系统中并不存在,所以为了兼容之前的系统,才会有app:这种写法。
同时我们发现ToolBar
和statusbar
的颜色保持一致,这里我们用到之前设置statusbar
的知识,设置为全屏然后接着设置statusbar
为透明色,这里特殊之处在于我们为Toolbar
设置的高度为wrap_content
并设置了一个最小的高度,这样就可以保证statusbar
处的颜色和Toolbar
的颜色一致。
接下来我们来具体分析这些属性该怎么用:
title、subtitle、logo、navigationicon的设置
这几个属性直接用app:
加上对应的属性名即可。
menu 和 navigationicon的点击事件设置:
其中menu的填充一定要在代码中执行,具体定义的步骤如下:
- 先在menu文件下面新建一个menu文件用来承载具体的menu的内容
1 | <menu xmlns:android="http://schemas.android.com/apk/res/android" |
- 在代码里面填充刚刚定义的menu文件
1 |
|
- 设置menu的点击事件
1 |
|
而我们之前设置的navigationicon的点击事件设置则更加简单,其具体代码如下:
1 | toolbar.setNavigationOnClickListener(new View.OnClickListener() { |
附:Toolbar可是一个viewgroup
在实际开发中我们会遇见一个两难的情况,我们希望Toolbar
的title
到中间去,但是Toolbar
似乎不给我们留什么修改它的接口,但是Material Design
的许多效果要搭配Toolbar
使用才行,比如说CollapsingToolbarLayout
。所以说我们得换一个思路,即把Toolbar
作为一个viewgroup
,具体的代码如下:
1 | <android.support.v7.widget.Toolbar |
这一段代码关键是设置了layot_gravity
和style
属性,其中style
把自定义的Textview
显示的和Actionbar.Title
保持一致,同时还需要在代码里面控制Actionbar
的title
不显示,具体的代码如下:
1 | getSupportActionBar().setDisplayShowTitleEnabled(false); |
附:利用actionLayout来模仿网易云
我在网上看到大神亦枫的博客,看到他利用Toolbar
做出了网易云音乐搜索栏的效果,感觉很牛逼。在通常情况下,Toolbar
的Menu item
只有一个icon
,但是有时候有些特殊情况,需要我们自定义Menu item
,最后完成的效果如下图所示:
我们需要额外定义一个layout
文件,然后通过actionLayout
属性引入到标签中。layout
具体代码如下:
1 | <RelativeLayout |
这里需要注意两点:
- 那个
layout
的跟布局必须是以RelativeLayout
作为根布局,否则,视图无法填满Toolbar
或者是Actionbar
。 - actionLayout这一属性必须是以app为命名空间。
将menu item移至中间
如果我们想把menu
移到中间来,而不是把它放到右边去,这个时候我们就需要想到用ActionMenuView
,其作为Toolbar的一个子控件,把menu item都放到自己里面,我们先来看看它的布局:
1 | <android.support.v7.widget.Toolbar |
接着在代码里把menu
资源文件加载到通过findViewById()
找到的ActionMenuView
里面去,具体的代码如下所示:
1 |
|
接着直接对ActionMenuView
设置点击事件,具体代码如下:
1 | amvSearch.setOnMenuItemClickListener(new ActionMenuView.OnMenuItemClickListener() { |
具体的效果图如下: