勇敢的少年啊,快来看看什么叫做抽屉导航之美吧~
前言
在Android中,很多App的主界面都使用了抽屉式导航,比如网易云音乐、Fuubo、Bilibili等,就我个人而言,我是非常喜欢这种导航方式的,顺便吐槽一下新版知乎,导航模式改为了底部导航,还取消了滑动返回,用的心累。
这是官方给出的示例图片,我觉得非常的漂亮,尤其是抽屉导航在状态栏的下方,当滑动抽屉的时候可以很明显的看出状态栏与抽屉之间的层次关系,而这也是今天我们要实现的效果,以下示例都运行在4.4版本上。
实现
首先看两个比较关键的属性,一个是:windowTranslucentStatus
这个属性支持的API最低为19,通常定义在values-v19/styles.xml下,它的作用是可以将状态栏的颜色置为透明色,还有一个是fitsSystemWindows
,这个属性的作用是确保内容不会显示到系统窗口下面,这里的系统窗口指的是StatusBar和NavigationBar。
全透明状态栏
首先看看网易云音乐在4.4上的表现
可以看到抽屉是在状态栏下面的,并且状态栏是完全透明的,要实现这样的效果也是很简单的,使用Toolbar替换ActionBar,在values-v19/styles.xml和values-v21/styles.xml中定义
windowTranslucentStatus
为true。代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="AppTheme.Base">
<item name="android:windowTranslucentStatus">true</item>
</style>
</resources>
activity_main代码:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="false"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/menu_drawer" />
</android.support.v4.widget.DrawerLayout>
要注意的是设置fitsSystemWindows为false。
其实到这里就已经实现了这个效果,不过可以发现toolbar会向上移动,有一部分被状态栏遮住,其实遮住的这一部分就是状态栏的高度,因为设置为true会,解决办法是可以在Activity中为toolbar添加顶部的padding,代码如下:
public class MainActivity extends AppCompatActivity {
private Toolbar mToolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
mToolbar.setPadding(0,getStatusBarHeight(),0,0);
}
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
}
最终效果:
着色状态栏
这种抽屉方式,在滑动的时候给人一种撕裂的感觉,看起来不是很舒服。
因为要给statusbar着色,所以要用到第三方库SystemBarTint,但要注意这个库已经被作者标记为DEPRECATED,即作者不赞成现在使用该库,这个与今天主题无关,就不多管了。
Android4.4(Kitkat)提出了透明状态栏的概念,可以为status bar或是Navigation bar 设置透明度,而SystemBarTint的出现使我们更加方便为status bar和 Navigation bar着色,可以设置color或是Drawable。
首先必须允许status bar 透明,在values-v19/styles.xml中添加
<item name="android:windowTranslucentStatus">true</item>
activity_main代码与上一个基本相同,只是不再需要fitsSystemWindows属性。
Activity代码:
public class MainActivity extends AppCompatActivity {
private Toolbar mToolbar;
private SystemBarTintManager mTintManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
mToolbar.setPadding(0, getStatusBarHeight(), 0, 0);
setTintManager();
}
@TargetApi(19)
private void setTintManager() {
mTintManager = new SystemBarTintManager(this);
mTintManager.setStatusBarTintEnabled(true);
mTintManager.setStatusBarTintColor(Color.parseColor("#2196F3"));
}
...
}
最终效果:
带透明度的状态栏
这种其实就是实现官方给出的那种效果,也需要搭配SystemBarTint,代码与相当于是上面两种的结合,只不过在设置statusbar颜色的时候设置的是#20000000,即使透明度为20%;
@TargetApi(19)
private void setTintManager() {
mTintManager = new SystemBarTintManager(this);
mTintManager.setStatusBarTintEnabled(true);
mTintManager.setStatusBarTintColor(Color.parseColor("#20000000"));
}
最终效果:
参考
Android and the transparent status bar
该使用 fitsSystemWindows 了!