快来看看 Android 上的抽屉导航之美吧~
前言 在 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。 代码如下:
1 2 3 4 5 6 <?xml version="1.0" encoding="utf-8"?> <resources> <style name="AppTheme" parent="AppTheme.Base"> <item name="android:windowTranslucentStatus">true</item> </style> </resources>
activity_main 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <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,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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 设置透明度,而 SystemBarTin t的出现使我们更加方便为status bar 和 Navigation bar着色,可以设置color或是Drawable。 首先必须允许 status bar 透明,在 values-v19/styles.xml
中添加1 <item name="android:windowTranslucentStatus">true</item>
activity_main 代码与上一个基本相同,只是不再需要 fitsSystemWindows 属性。 Activity 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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
;
1 2 3 4 5 6 @TargetApi(19) private void setTintManager() { mTintManager = new SystemBarTintManager(this); mTintManager.setStatusBarTintEnabled(true); mTintManager.setStatusBarTintColor(Color.parseColor("#20000000")); }
最终效果:
参考 Android and the transparent status bar 该使用 fitsSystemWindows 了!