当前位置:   article > 正文

DrawerLayout和NavigationView轻松实现抽屉侧滑_toggle.drawerarrowdrawable

toggle.drawerarrowdrawable

在android5.0后谷歌添加了DrawerLayout和NavigationView两个控件,使用这两个控件可以很轻松的实现抽屉侧滑效果,这里说先DrawerLayout;

DrawerLayout: 
DrawerLayout是MateriaDesign风格中的控件,来自support-v4包里面,相当于一个自定义容器 extends ViewGroup ,可以看作是一个有侧滑效果的帧布局。

1、DrawerLayout+ToolBar实现抽屉侧滑 
在使用DrawerLayout的时候要将DrawerLayout作为内容布局和侧滑菜单布局的父布,

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical">
  7. <android.support.v7.widget.Toolbar
  8. android:id="@+id/toolbar"
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:background="@color/colorPrimary">
  12. </android.support.v7.widget.Toolbar>
  13. <android.support.v4.widget.DrawerLayout
  14. android:id="@+id/drawer_layout"
  15. android:layout_width="match_parent"
  16. android:layout_height="match_parent"
  17. tools:context="com.drawerlayoutdemo.MainActivity">
  18. <!--内容部分-->
  19. <ListView
  20. android:id="@+id/content_list"
  21. android:layout_width="match_parent"
  22. android:layout_height="match_parent">
  23. </ListView>
  24. <!--侧滑菜单部分左边-->
  25. <ListView
  26. android:id="@+id/left"
  27. android:layout_width="150dp"
  28. android:layout_gravity="start"
  29. android:layout_height="match_parent"
  30. android:background="@android:color/white">
  31. </ListView>
  32. <!--侧滑菜单部分右边-->
  33. <ListView
  34. android:id="@+id/right"
  35. android:layout_width="match_parent"
  36. android:layout_marginLeft="50dp"
  37. android:layout_gravity="end"
  38. android:layout_height="match_parent"
  39. android:background="@android:color/white">
  40. </ListView>
  41. </android.support.v4.widget.DrawerLayout>
  42. </LinearLayout>
  • 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
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

在侧滑菜单布局中要添加android:layout_gravity=”end”,这样DrawerLayout才会辨别哪个是侧滑菜单,这里提供了是个属性值;

@IntDef({Gravity.LEFT, Gravity.RIGHT, GravityCompat.START, GravityCompat.END})
 
 
  • 1

LEFT和START表示左边侧滑,RIGHT和END表示右边侧滑,GravityCompat.START和GravityCompat.END是为了兼容低版本,布局文件写好后,将布局文件中的控件引入进来;

  1. drawerLayout= (DrawerLayout) findViewById(R.id.drawer_layout);
  2. toolbar= (Toolbar) findViewById(R.id.toolbar);
  3. //设置Toolbar
  4. setSupportActionBar(toolbar);
  5. //将DrawerLayout和Toolbar关联
  6. ActionBarDrawerToggle toggle=new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.drawer_open,R.string.drawer_close);
  7. //进行同步
  8. toggle.syncState();
  9. //添加事件监听
  10. drawerLayout.addDrawerListener(toggle);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

没错就这些代码就已经实现了一个抽屉侧滑效果; 
这里写图片描述 
实现了左右侧滑,点击ToolBar左边可以打开或关闭侧滑菜单,点击条目同样可以响应点击事件;

DrawerLayout单独使用实现抽屉侧滑 
如果不想结合ToolBar来实现侧滑效果也是可以的,下面这个就是DrawerLayout单独使用实现抽屉侧滑,布局文件还是一样的没有变化,只是将标题栏改成了RelativeLayout,RelativeLayout里面放了一个imageview,点击imageview或者ListView条目来控制DrawerLayout打开或关闭;

  1. iv.setOnClickListener(new View.OnClickListener() {
  2. @Override
  3. public void onClick(View v) {
  4. index++;
  5. if (index % 2 == 0) {
  6. //打开
  7. drawerLayout.openDrawer(GravityCompat.START, true);
  8. } else {
  9. //关闭
  10. drawerLayout.closeDrawer(GravityCompat.START, true);
  11. }
  12. }
  13. });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

调用DrawerLayout里面的openDrawer或者closeDrawer就可以设置打开还是关闭,不过在设置的时候要注意,GravityCompat.START要和布局文件中的android:layout_gravity=”start”要相对应,这样就可以了; 
这里写图片描述

注:点击条目打开右边侧滑菜单的效果有点类似于易车网App选车列表效果

如果只是想点击的时候打开侧滑菜单,左右滑动的时候不打开也是可以的,调用setDrawerLockMode();就可以设置打开还是关闭;lockMode参数有四个选择:

  1. /**
  2. * The drawer is unlocked.
  3. */
  4. public static final int LOCK_MODE_UNLOCKED = 0;
  5. /**
  6. * The drawer is locked closed. The user may not open it, though
  7. * the app may open it programmatically.
  8. */
  9. public static final int LOCK_MODE_LOCKED_CLOSED = 1;
  10. /**
  11. * The drawer is locked open. The user may not close it, though the app
  12. * may close it programmatically.
  13. */
  14. public static final int LOCK_MODE_LOCKED_OPEN = 2;
  15. /**
  16. * The drawer's lock state is reset to default.
  17. */
  18. public static final int LOCK_MODE_UNDEFINED = 3;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  1. //设置左边和右边关闭或者打开
  2. public void setDrawerLockMode(@LockMode int lockMode) {
  3. setDrawerLockMode(lockMode, Gravity.LEFT);
  4. setDrawerLockMode(lockMode, Gravity.RIGHT);
  5. }
  • 1
  • 2
  • 3
  • 4
  • 5
  1. //设置左边或者右边打开或者关闭 edgeGravity可以是Gravity.LEFT, //Gravity.RIGHT, GravityCompat.START, GravityCompat.END里
  2. //面的任意一个
  3. public void setDrawerLockMode(@LockMode int lockMode, @EdgeGravity int edgeGravity) {
  4. ...
  5. }
  • 1
  • 2
  • 3
  • 4
  • 5
  1. //指定对应的View侧滑打开或者关闭
  2. public void setDrawerLockMode(@LockMode int lockMode, View drawerView) {
  3. ...
  4. setDrawerLockMode(lockMode, gravity);
  5. }
  • 1
  • 2
  • 3
  • 4
  • 5

第一个和第三个最终还是调用的是第二个;接下来就去看看DrawerLayout的源码;

DrawerLayout源码:

  1. public DrawerLayout(Context context, AttributeSet attrs, int defStyle) {
  2. super(context, attrs, defStyle);
  3. ...
  4. mLeftDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mLeftCallback);
  5. mLeftDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
  6. mLeftDragger.setMinVelocity(minVel);
  7. mLeftCallback.setDragger(mLeftDragger);
  8. mRightDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mRightCallback);
  9. mRightDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_RIGHT);
  10. mRightDragger.setMinVelocity(minVel);
  11. mRightCallback.setDragger(mRightDragger);
  12. ...
  13. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在DrawerLayout构造方法里面可以看到DrawerLayout是利用ViewDragHelper这里类来实现侧滑效果的;在DrawerLayout和ToolBar结合使用的时候还涉及到了ActionBarDrawerToggle类, 
ActionBarDrawerToggle类提供了两个构造方法;

  1. public ActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout,
  2. @StringRes int openDrawerContentDescRes,
  3. @StringRes int closeDrawerContentDescRes) {
  4. this(activity, null, drawerLayout, null, openDrawerContentDescRes,
  5. closeDrawerContentDescRes);
  6. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. public ActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout,
  2. Toolbar toolbar, @StringRes int openDrawerContentDescRes,
  3. @StringRes int closeDrawerContentDescRes) {
  4. this(activity, toolbar, drawerLayout, null, openDrawerContentDescRes,
  5. closeDrawerContentDescRes);
  6. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

调用syncState();方法后就将ToolBar和DrawerLayout同步,

  1. public void syncState() {
  2. if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
  3. setPosition(1);
  4. } else {
  5. setPosition(0);
  6. }
  7. ...
  8. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  1. private void setPosition(float position) {
  2. if (position == 1f) {
  3. mSlider.setVerticalMirror(true);
  4. } else if (position == 0f) {
  5. mSlider.setVerticalMirror(false);
  6. }
  7. mSlider.setProgress(position);
  8. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

走到这里涉及到DrawerArrowDrawable类,DrawerArrowDrawable extend Drawable,根据传进来的position调用DrawerArrowDrawable 中的setProgress();方法进行绘制;

  1. public void setProgress(@FloatRange(from = 0.0, to = 1.0) float progress) {
  2. if (mProgress != progress) {
  3. mProgress = progress;
  4. //进行绘制,最终调用父类中的方法进行绘制drawable
  5. invalidateSelf();
  6. }
  7. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Drawable类中的invalidateSelf();方法

  1. public void invalidateSelf() {
  2. final Callback callback = getCallback();
  3. if (callback != null) {
  4. callback.invalidateDrawable(this);
  5. }
  6. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这样就会在侧滑菜单打开或关闭的时候,对三道杠或者箭头进行切换绘制;如果想在打开或关闭的时候进行监听添加其他效果可以调用DrawerLayout中的setDrawerListener或者addDrawerListener,不过建议调用addDrawerListener,setDrawerListener已经过时了,

  1. @Deprecated
  2. public void setDrawerListener(DrawerListener listener) {
  3. //如果之前的DrawerListener还存在就将其移除调
  4. if (mListener != null) {
  5. removeDrawerListener(mListener);
  6. }
  7. //添加新的DrawerListener
  8. if (listener != null) {
  9. addDrawerListener(listener);
  10. }
  11. //将新的DrawerListener赋值给之前的DrawerListener
  12. mListener = listener;
  13. }
  14. public void addDrawerListener(@NonNull DrawerListener listener) {
  15. if (listener == null) {
  16. return;
  17. }
  18. //利用集合来管理DrawerListener
  19. if (mListeners == null) {
  20. mListeners = new ArrayList<DrawerListener>();
  21. }
  22. mListeners.add(listener);
  23. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  1. //给侧滑控件设置监听
  2. drawerlayout.setDrawerListener(new DrawerListener() {
  3. @Override
  4. public void onDrawerStateChanged(int newState) {
  5. // 状态发生改变
  6. }
  7. @Override
  8. public void onDrawerSlide(View drawerView, float slideOffset) {
  9. // 滑动的过程当中不断地回调 slideOffset:0~1
  10. }
  11. @Override
  12. public void onDrawerOpened(View drawerView) {
  13. // 打开
  14. }
  15. @Override
  16. public void onDrawerClosed(View drawerView) {
  17. // 关闭
  18. }
  19. });
  • 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

如果不想实现全部方法的话可以使用SimpleDrawerListener,SimpleDrawerListener implements DrawerListener;

  1. public abstract static class SimpleDrawerListener implements DrawerListener {
  2. @Override
  3. public void onDrawerSlide(View drawerView, float slideOffset) {
  4. }
  5. @Override
  6. public void onDrawerOpened(View drawerView) {
  7. }
  8. @Override
  9. public void onDrawerClosed(View drawerView) {
  10. }
  11. @Override
  12. public void onDrawerStateChanged(int newState) {
  13. }
  14. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这样可以根据自己的需要进行方法的重写,其他的一些方法在使用的时候可以细看源码,总的来说DrawerLayout使用起来还是比较灵活的;

NavigationView 
NavigationView也是谷歌在android5.0推出来的一个侧滑控价,目的是为了用来规范侧滑的基本样式;NavigationView使用的时候要结合DrawerLayout一起使用;

1、引入依赖库

compile 'com.android.support:design:26.0.0-alpha1'
 
 
  • 1

2、在xml文件中使用 
将DrawerLayout作为内容布局和侧滑菜单布局的父布局,使用NavigationView作为侧滑菜单;

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent">
  6. <!-- 内容部分 -->
  7. <FrameLayout
  8. android:id="@+id/fl"
  9. android:layout_width="fill_parent"
  10. android:layout_height="fill_parent"
  11. />
  12. <!-- 菜单部分 -->
  13. <android.support.design.widget.NavigationView
  14. android:layout_gravity="start"
  15. android:layout_width="wrap_content"
  16. android:layout_height="fill_parent"
  17. app:menu="@menu/navigation_menu"
  18. app:headerLayout="@layout/navigation_headerlayout"
  19. />
  20. </android.support.v4.widget.DrawerLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  1. app:menu 侧滑菜单的条目
  2. app:headerLayout 侧滑菜单条目上面的头部布局
  • 1
  • 2

这样效果就实现了,是不是比DrawerLayout还要简单; 
这里写图片描述 
但是NavigationView是为了规范侧滑的基本样式的,侧滑菜单的样式就不好改变,条目就只能采用menu的方式实现,使用起来就没有DrawerLayout那么灵活,在开发中,效果不是很炫的话,可以使用DrawerLayout来实现,当前自定义的话也可以。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/314812
推荐阅读
相关标签
  

闽ICP备14008679号