实现 Material Design 抽屉式导航栏微件,我们也可以使用这个控件来做左右展开功能!!!
引入
dependencies {
implementation "androidx.drawerlayout:drawerlayout:1.1.1"
}
最新版本可以查看官方文档
基础使用
1、xml布局
<androidx.drawerlayout.widget.DrawerLayout
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#2196F3"
android:gravity="center"
android:orientation="vertical"
android:text="内容区域" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#F44336"
android:gravity="center"
android:text="左边抽屉" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="end"
android:background="#E91E63"
android:gravity="center"
android:text="右边抽屉" />
</androidx.drawerlayout.widget.DrawerLayout>
DrawerLayout是根据控件的android:layout_gravity
属性来判断是否为内容区域和滑动菜单的
- 没有设置layout_gravity,那么为内容区域
- 设置
android:layout_gravity="start"
,那么为左边划出菜单 - 设置
android:layout_gravity="end"
,那么为右边划出菜单
2、代码中使用
//打开抽屉
open()//默认打开左边的
openDrawer()//可以指定打开哪边的
//关闭抽屉
close()//默认关闭左边的
closeDrawers()//关闭所有打开的
监听回调
mBinding.drawerLayout.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
Log.i(TAG, "onDrawerSlide: " + slideOffset);
}
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
Log.i(TAG, "onDrawerOpened: ");
}
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
Log.i(TAG, "onDrawerClosed: ");
}
@Override
public void onDrawerStateChanged(int newState) {
super.onDrawerStateChanged(newState);
Log.i(TAG, "onDrawerStateChanged: " + newState);
}
});
一些问题
问题一: java.lang.IllegalArgumentException: DrawerLayout must be measured with MeasureSpec.EXACTLY
查看源码可以知道,当DrawerLayout或者父布局的宽高为wrap_content报错
DrawerLayout#onMeasure
if (widthMode != View.MeasureSpec.EXACTLY || heightMode != View.MeasureSpec.EXACTLY) {
if (isInEditMode()) {
// Don't crash the layout editor. Consume all of the space if specified
// or pick a magic number from thin air otherwise.
// TODO Better communication with tools of this bogus state.
// It will crash on a real device.
if (widthMode == View.MeasureSpec.UNSPECIFIED) {
widthSize = 300;
}
if (heightMode == View.MeasureSpec.UNSPECIFIED) {
heightSize = 300;
}
} else {
throw new IllegalArgumentException(
"DrawerLayout must be measured with MeasureSpec.EXACTLY.");
}
}
问题二:滑动菜单需要填满屏幕
查看源码可以知道,DrawerLayout的划出菜单默认边距为60dp,主要是变量mMinDrawerMargin来控制,通过反射修改即可。
try {
Class<? extends DrawerLayout> aClass = mBinding.drawerLayout.getClass();
Field mMinDrawerMargin = aClass.getDeclaredField("mMinDrawerMargin");
mMinDrawerMargin.setAccessible(true);
mMinDrawerMargin.setInt(mBinding.drawerLayout, 0);
} catch (Exception e) {
e.printStackTrace();
}
问题三:去掉阴影部分
mBinding.drawerLayout.setScrimColor(Color.TRANSPARENT);
阴影的具体实现在DrawerLayout#drawChild中