安卓项目实战之DrawerLayout+NavigationView+ToolBar实现抽屉式侧边栏效果

效果图

添加依赖

由于用到v4包下DrawerLayout,v7包下Toolbar,和android.support.design下的NavigationView,需要在gradle中作如下配置:

v4包系统默认引入
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.3.1'

DrawerLayout

 如果我们希望整个界面整体可以侧滑,我们可以把DrawerLayout作为整个界面的根布局。

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dl_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >  
	<!--内容界面布局-->
	<!--左菜单界面布局-->
	<!--右菜单界面布局-->
</android.support.v4.widget.DrawerLayout>

DrawerLayout为了识别或智能的控制内容布局、左菜单布局、右菜单布局,对三者的放置顺序做了限定,要求内容布局必须放在其它两个布局的前面

如果把菜单布局放到内容布局前面,运行程序会报类型转换异常,这也说明它对放置顺序做了限定,与此同时需要在左菜单根布局添加:

android:layout_gravity = "start"或"left"控制它在左边,DrawerLayout识别它作为左菜单布局,同样如果有右菜单界面,则右菜单根布局需要添加:

android:layout_gravity = "end"或 "right"控制它在右边,DrawerLayout识别它为右菜单布局。

 

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dl_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

   <!--内容界面布局-->
    <LinearLayout
        android:id="@+id/ll_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

    </LinearLayout>

    <!--左菜单界面布局-->
    <RelativeLayout
        android:id="@+id/rl_left_menu"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#ffffff" >

      
    </RelativeLayout>

    <!--右菜单界面布局-->
    <RelativeLayout
        android:id="@+id/rl_right_menu"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_gravity="end"
        android:background="#ffffff" >

      
    </RelativeLayout>

</android.support.v4.widget.DrawerLayout>

 对按钮添加点击事件来控制侧边栏的打开和关闭:

mLeftIb.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				//判断左菜单是否打开,如果没有,则的开,否则关闭左菜单
				if(!mDrawerL.isDrawerOpen(Gravity.LEFT)){
					Toast.makeText(MainActivity.this, "打开左菜单", Toast.LENGTH_SHORT).show();
					mDrawerL.openDrawer(Gravity.LEFT);
				}else{
					mDrawerL.closeDrawer(Gravity.LEFT);
				}
			}
		});

 

NavigationView

我们做抽屉菜单的时候,左边滑出来的那一部分的布局都是由我们自己来定义的,自己写的话,花点时间也能做出来好看的侧拉菜单,但总是要耗费时间,于是Google在5.0之后推出了NavitationView,就是我们左边滑出来的那个菜单。这个菜单整体上分为两部分,上面一部分叫做HeaderLayout,下面的那些点击项都是menu,这样的效果如果我们要自己写肯定也能写出来,但是没有必要,既然Google提供了这个控件,那我们就来看看这个控件要怎么用吧。

 和普通的侧拉菜单制作方式一样,首先所有的东西还是都放在一个DrawerLayout中,只不过这次我们把左边滑出菜单的布局用一个NavigationView来代替,代码如下:

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout 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"
    android:fitsSystemWindows="true"> 
<android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"> 
<android.support.design.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">                                                                            <android.support.design.widget.AppBarLayout
                android:id="@+id/appbar_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?actionBarSize"
                    android:background="?attr/colorPrimary"
                    app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> 
<!--内容 -可切换Fragment--> 
<LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                app:layout_behavior="@string/appbar_scrolling_view_behavior"> <TextView
                    android:id="@+id/message"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" /> <Button
                    android:id="@+id/nextButton"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:text="测试" /> 
</LinearLayout> 
</android.support.design.widget.CoordinatorLayout> 
<!--左侧导航菜单--> 
<android.support.design.widget.NavigationView
            android:id="@+id/navigation_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="@color/windowBackground"
            app:headerLayout="@layout/navigation_header"
            app:menu="@menu/drawer" /> 
</android.support.v4.widget.DrawerLayout> 
</FrameLayout>

分别解释一下这里边几个属性的含义: 

1.Android:layout_gravity=”left”属性表示该View是左边的滑出菜单,这个属性的含义不用多说,这是DrawerLayout使用方式中的知识点。NavigationView需要设置 android:layout_gravity=”start”
2.app:headerLayout=”@layout/header_layout”表示引用一个头布局文件,这个头就是我们在上面看到的那个背景图片,包括背景图片上面的显示用户名的控件等等。
3.app:menu=”@menu/main”表示引用一个menu作为下面的点击项

头布局文件:

<?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"
    android:id="@+id/ll_navigation_header"
    android:layout_width="match_parent"
    android:layout_height="192dp"
    android:background="?attr/colorPrimary"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="16dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark"> 
<ImageView
        android:id="@+id/profile_image"
        android:layout_width="72dp"
        android:layout_height="72dp"
        android:layout_marginTop="20dp"
        android:src="@mipmap/logo"
         /> 
<TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="HSY"
        android:textColor="#ffffff"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1"
        android:textSize="18sp" /> 
</LinearLayout>

 再来看看menu文件:

<?xml version="1.0" encoding="utf-8"?> 
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"> 
<group android:checkableBehavior="single"> 
<item
            android:checked="true"
            android:id="@+id/navigation_item_home"
            android:icon="@drawable/iconfont_home"
            android:title="首页" /> 
<item
            android:id="@+id/navigation_item_ganhuo"
            android:icon="@drawable/iconfont_source"
            android:title="干货" /> 
<item
            android:id="@+id/navigation_item_blog"
            android:icon="@drawable/iconfont_blog"
            android:title="我的博客" /> 
<item
            android:id="@+id/navigation_item_custom_view"
            android:icon="@drawable/iconfont_custom_view"
            android:title="自定义View" /> 
<item
            android:id="@+id/navigation_item_snackbar"
            android:icon="@drawable/iconfont_custom_view"
            android:title="Snackbar演示" /> 
<item android:title="其他"> 
<menu> 
<item
                    android:id="@+id/navigation_item_switch_theme"
                    android:checkable="true"
                    android:icon="@drawable/iconfont_skin"
                    android:title="主题换肤" /> 
<item
                    android:id="@+id/navigation_item_about"
                    android:checkable="true"
                    android:icon="@drawable/iconfont_about"
                    android:title="关于" /> 
</menu> 
</item> 
</group> 
</menu>

1.在布局文件中添加app:itemIconTint=”@color/blue”属性,表示设置图片的颜色全都为蓝色,如果我想让图片就是显示他本身的颜色该怎么办呢?在Java代码中调用如下方法:

NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_view);  
        navigationView.setItemIconTintList(null);  

还有下面两个常用的API: 

1.app:itemBackground="@color/colorAccent"设置每一个item的背景颜色
2.app:itemTextColor=""设置item的背景颜色

2.如果我想在NavigationView的item之间添加上一条分隔线呢?很简单,只需要在menu中将相应的item放到一个group中,并给该group取一个id即可,代码如下:

<?xml version="1.0" encoding="utf-8"?> 
<menu xmlns:android="http://schemas.android.com/apk/res/android"> 
<group android:id="@+id/g1"> 
<item  
            android:id="@+id/favorite"  
            android:icon="@mipmap/ic_launcher"  
            android:title="收藏"/> 
<item  
            android:id="@+id/wallet"  
            android:icon="@mipmap/ic_launcher"  
            android:title="钱包"/> 
</group> 
<group android:id="@+id/g2"> 
<item  
            android:id="@+id/photo"  
            android:icon="@mipmap/ic_launcher"  
            android:title="相册"/> 
</group> 
<item  
        android:id="@+id/file"  
        android:icon="@mipmap/ic_launcher"  
        android:title="文件"/> 
</menu>

3.隐藏某个菜单列表项,公司项目会根据你是否是管理员,来控制某个菜单列表项的显示和隐藏,因此就出现了这个问题。

MenuItem menuItem = navigationView.getMenu().findItem(R.id.some_menu_item);
menuItem.setVisible(false); // true 为显示,false 为隐藏

4. 使用 NavigationView 时透明状态栏的处理

Android App 沉浸式状态栏解决方案

 NavigationView中的事件监听

 1.头部点击事件

处理头部点击事件,我们需要先获得到头部控件,在Java代码中我们可以通过下面的方式获得头部控件,

//获取头布局文件  
View headerView = navigationView.getHeaderView(0);  

然后通过调用headerView中的findViewById方法来查找到头部的控件,设置点击事件即可。

2.item点击事件

navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {  
   @Override 
   public boolean onNavigationItemSelected(MenuItem item) { 
   //在这里处理item的点击事件  
   return true; 
} 
});

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智玲君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值