DrawerLayout给我们提供的屏幕滑动拖出选项栏功能,并且布局的过程非常简单。
这个是哔哩哔哩的布局用的就是DrawerLayout,从屏幕左边滑动便可以拖出菜单栏。
文章大纲:
1:什么是DrawerLayout:
2:如何布局Drawerlayout:
3:丰富多彩的Drawerlayout:
环节一: <关于DrawerLayout>
来看看DrawerLayout继承结构:
DrawerLayout是继承的ViewGroup, 我们都知道平时使用的FrameLayout,LinearLayout.....同样都是继承了ViewGroup,所以DrawerLayout的使用也大径相同。而DrawerLayout能滑动无非就是实现了 View的OnTouch或OnTouchEvent方法:
进去源码一看确实,DrawerLayout实现了OnTouchEvent()方法,而FrameLayout等等并没有实现。 方法的具体实现对于我们初学者而言是比较难的,所以知道内部的运行过程即可。
环节二:<如何布局Drawerlayout>
经过了环节一相信大家已经差不多知道如何使用了, 其实就是在需要实现滑动的View上加上父布局DrawerLayout。这样在DrawerLayout能接受到触摸事件的情况下,便会产生相应动作。看xml:
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start" android:background="@android:color/holo_green_light"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="你好,陌生人" android:gravity="center" /> </FrameLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="50dp" android:layout_height="50dp" android:text="onClick" android:gravity="center"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="nihao"/>
</LinearLayout> </android.support.v4.widget.DrawerLayout>
上面的xml就是一个DrawerLayout包裹两个Layout,来看看界面是什么样子:
为什么FrameLayout会被放在菜单栏里?
android:layout_gravity="start"
就是因为这个属性。 除了start外还可以填left,right, 表示从哪个方向滑动。start表示根据语言设置默认。
一个在DrawerLayout里的第一层View有这个属性就会被DrawerLayout识别,将其放在菜单栏,其他放在主界面。
这个主界面只能放一个View,否则会参数异常。 所以一般就放一个布局即可。看看上述去掉的<LinearLayout>标签后:
即使我调整button的大小为50dp,但是button任然占据全屏,所以一般我们就放入一个Layout。 同样DrawerLayout也可放在一个Layout内部,只要它能响应触摸事件就都可以。 大小同样可以改变。
环节三: <丰富多彩的Drawerlayout>
除了我们可以自定义View放入DrawerLayout内部外,官方还给我们提供了另一个组件 NavigationView;
看看这个NavigationView继承关系
NavigationView 最终还是继承FrameLayout的, 而这个NavigationView要放的位置就是上述的FrameLayout的位置,替换后:
<android.support.design.widget.NavigationView android:id="@+id/navigationView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start" android:background="@android:color/holo_green_light" app:menu="@menu/menu" app:headerLayout="@layout/head" > </android.support.design.widget.NavigationView>
navigationView与Framelayout不同的是,navigation支持app:menu与app:headerLayout
这两个参数, menu:是navigationView里的menu组,headerLayout:是一块自定义Layout区域:
navigationView的上部是笔者自定义的Layout,下部是一个menu的xml文件, 看看menu怎么定义吧:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@+id/menu" android:icon="@mipmap/menu" android:title="menu" ></item> <item android:id="@+id/delete" android:icon="@mipmap/delete" android:title="delete" ></item> <item android:id="@+id/post" android:icon="@mipmap/post" android:title="post" ></item> </group> </menu>
尽量用<group>标签包裹 ,这样就可以使用一些按钮组属性了 比如android:checkableBehavior="single" 设置只能单选
ok说到点击事件那就来看看怎样为navigation设置点击事件:
navigationView= (NavigationView) findViewById(R.id.navigationView); navigationView.setCheckedItem(R.id.menu); navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { Toast.makeText(Main.this, item.getTitle(), Toast.LENGTH_SHORT).show(); return false; } }); }
首先得到navigationView的实例,然后用navigationView.setCheckedItem(R.id.menu)设置默认选中位置(不设置也可以), 然后设置点击事件。
ok 运行 发现navigation并不能响应: 其实这里并不是代码的问题,而是XML文件位置问题。我们将XML文件的navigationView标签放到下方:
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="50dp" android:layout_height="50dp" android:text="onClick" android:gravity="center"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="nihao"/> </FrameLayout> <android.support.design.widget.NavigationView android:id="@+id/navigationView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start" android:background="@android:color/holo_green_light" app:menu="@menu/menu" app:headerLayout="@layout/head" > </android.support.design.widget.NavigationView> </android.support.v4.widget.DrawerLayout>
ok 这样就没问题了。 具体什么原因还有待研究。
顺便说一下navigationView的menu文字颜色也可以自定义的:如果我们没有给他设定,
那颜色值就是黑色,一个view创建会先从Activity的属性值里读取自己需要的属性然后设定,
然后再读取自己的属性值,自己的属性值最终会覆盖读取Activity的属性值。所以我们可在自己的标签
里添加
app:itemTextColor="" 便可以修改navigationView的默认字体颜色, Activit中也可以。
<item name="colorPrimary"></item> 这个属性修改用
navigationView.setCheckedItem(R.id.menu)选中的字体颜色,在Activity里设定。
当然还有其他的属性笔者就不啰嗦了。 goodbye!