Drawerlayout小结

实现 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中


版权声明:本文为weixin_43976461原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>