DrawLayout我们应该使用androidx.drawerlayout.widget.DrawerLayout
并非V4版本的android.support.v4.widget.DrawerLayout
和DrawerLayout类似的控件还包括SlidingPaneLayout,有兴趣的可以去了解一下。
首先简单过一下DrawerLayout源码(这里截取重点)
public class DrawerLayout extends ViewGroup {
...
private final ViewDragHelper mLeftDragger;
private final ViewDragHelper mRightDragger;
private final ViewDragCallback mLeftCallback;
private final ViewDragCallback mRightCallback;
...}
从源码可以看出DrawLoyout就是从ViewGroup实现,即View的容器。所以直接把DrawerLayout当做一个普通容器使用即可。
DrawerLayout只允许两个直接子View。第一个子View为主View,第二个子View为抽屉View
第二个View我们通常会选择使用NavigationView
下面就是一个简单的DrawerLayout布局
<androidx.drawerlayout.widget.DrawerLayout
android:id="@+id/drawer_layout1"
android:layout_width="match_parent"
android:layout_height="200dp"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<LinearLayout
android:id="@+id/view_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<Button
android:id="@+id/btn_2"
android:text="test"
android:layout_height="200dp"
android:layout_width="200dp"/>
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/view_2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="false">
<TextView
android:id="@+id/text_2"
android:text="Hellow word"
android:gravity="center"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
DrawerLayout 属性和普通控件没什么区别,唯一多的一个就是tools:openDrawer=“start”,其功能辅助Android studio 视图预览。如果配置了tools:openDrawer,那么在视图中我们就能看见抽屉展开后的效果。tools:属性不会编译到apk中,只是作为视图辅助使用。属性start或者end,这个由抽屉视图的打开方向决定。
抽屉视图:即子视图2。作为子视图我们应该告知DrawerLayout的抽屉方向android:layout_gravity=“start”,start:从左边打开,end从右边打开。
NavigationView
在Material Design中,Navigation
drawer导航抽屉,被设计用于应用导航,提供了一种通用的导航方式,体现了设计的一致性。
而NavigationView的典型用途就是配合之前v4包的DrawerLayout,作为其中的Drawer部分,即导航菜单的本体部分。NavigationView是一个导航菜单框架,使用menu资源填充数据,使我们可以更简单高效的实现导航菜单。它提供了不错的默认样式、选中项高亮、分组单选、分组子标题、以及可选的Header。
注意其中NavigationView的两个自定义属性
app:headerLayout接收一个layout,作为导航菜单顶部的Header,可选项。
app:menu接收一个menu,作为导航菜单的菜单项,几乎是必选项,不然这个控件就失去意义了。但也可以在运行时动态改变menu属性。
用于NavigationView的典型menu文件,应该是一个可选中菜单项的集合。其中checked=”true”的item将会高亮显示,这可以确保用户知道当前选中的菜单项是哪个。item的选中状态可以在代码中设置
此处由于我需要尽可能的简化DrawerLayout的使用,所以就不细讲NavigationView。如果需要了解的可以通过File->New->New Project->Navigation Drawer Activity
查看该工程源码。
所以最简单的DrawerLayout使用方法:
<DrawerLayout>
<!-- 子视图1,作为DrawerLayout主视图 -->
<View1>
</View1>
<!-- 子视图2,作为DrawerLayout抽屉视图 -->
<View2 layout_gravity="start">
</View2>
</DrawerLayout>
下面就是一个最简单的抽屉视图Demo
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:fitsSystemWindows="true">
<LinearLayout android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@drawable/ic_launcher_background"/>
<androidx.drawerlayout.widget.DrawerLayout
android:id="@+id/drawer_layout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<LinearLayout
android:id="@+id/content_frame1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/text_0"
android:text="我是主视图1"
android:gravity="center"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="false">
<TextView
android:id="@+id/text_2"
android:text="我是抽屉视图"
android:gravity="center"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
</LinearLayout>
包含多DrawerLayout的视图,drawer_item_layout.xml.
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<LinearLayout
android:id="@+id/content_frame1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/text_0"
android:text="我是主视图1"
android:gravity="center"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="false">
<TextView
android:id="@+id/text_2"
android:text="我是展开的抽屉"
android:gravity="center"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
MainActivity.xml修改成如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:fitsSystemWindows="true">
<LinearLayout android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@drawable/ic_launcher_background"/>
<include layout="@layout/drawer_item_layout"
android:layout_height="200dp"
android:layout_width="match_parent" />
<include layout="@layout/drawer_item_layout"
android:layout_height="200dp"
android:layout_width="match_parent" />
<include layout="@layout/drawer_item_layout"
android:layout_height="200dp"
android:layout_width="match_parent" />
</LinearLayout>
上述视图的抽屉我们都是使用NavigationView,那么能否改用其他的呢?答案是OK的。
下面我们将使用LinearLayout替换NavigationView。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:fitsSystemWindows="true">
<LinearLayout android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@drawable/ic_launcher_background"/>
<androidx.drawerlayout.widget.DrawerLayout
android:id="@+id/drawer_layout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<LinearLayout
android:id="@+id/content_frame1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/text_0"
android:text="我是主视图1"
android:gravity="center"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</LinearLayout>
<LinearLayout
android:id="@+id/nav_view2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@color/colorPrimaryDark"
android:fitsSystemWindows="false">
<TextView
android:id="@+id/text_2"
android:text="我是展开的抽屉"
android:textColor="#ff0000"
android:gravity="center"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</LinearLayout>
</androidx.drawerlayout.widget.DrawerLayout>
</LinearLayout>
至于子视图2是否可以使用其他具体更多的View代替,例如FrameLayout那肯定也可以的,因为NavigationView就是从FrameLayout继承而来。
此时DrawerLayout的使用基本就OK了。但是不知道你是否还记得本文一开始就提到过的ViewDragHelper 这才是DrawerLayout实现的关键,下一章我们将对其进行讲解。