您的位置:首页 > 移动开发 > Android开发

Android利用DrawerLayout实现侧滑菜单

2017-03-15 23:19 513 查看
侧滑菜单是Android5.0 Material Design中最常见的效果之一,现在市场上很多的应用都有滑动菜单的功能,如qq。利用google提供的工具,我们也可以轻松实现这种效果。这种侧滑菜单将一些功能菜单隐藏起来,手指滑动时可以显示出来,点击可以跳转到相应的功能界面,这样可以有效的节省屏幕空间。

现在我们利用系统提供的DrawerLayout控件,实现侧滑菜单不仅简单,而且很方便。效果图如下:



看名字就知道,它是一个布局,在这个布局文件中可以放两个直接子控件,第一个是屏幕显示的主内容,第二个子控件是滑动时,菜单显示的内容。

布局代码如下:

activity_main.xml

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

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimaryDark"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

</android.support.v7.widget.Toolbar>
</FrameLayout>

<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/nav_header"
app:menu="@menu/nav_menu">

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


上面的包含了一个Toobar控件,为了让我们的界面更好看,我就添加进去了,如果单独要实现侧滑菜单效果的话,是不用的。这里就顺便写一下吧。然后最后的NavigationView控件,是存放菜单选项布局的,当然我们也可以不用这个,自己去实现布局,因为用navigationView比较简单,布局也好看,所以就采用了。

DrawerLayout是support-v4库提供的,可以看到我们放置了两个子控件,一个是FrameLayout,用于显示主屏幕的内容(包含了Toolbar控件),另一个是菜单项的布局,这里采用的是NavigationView控件,但是其中有个点要注意的是

android:layout_gravity="start"
这个要指定,因为这个属性是为了告诉系统滑动菜单选项放置的位置。指定left是在左边,这里指定的是start,表示是指系统语言是从左往右读的话,比如:汉语,英语,那么控件就在左边,反之是在右边,比如:阿拉伯语是从右往左读的。不得不佩服google考虑的真周到。

MainActivyt.java

package com.example.administrator.myapplication;

import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawerLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar= (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mDrawerLayout= (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBar actionBar=getSupportActionBar();
if (actionBar!=null){
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeAsUpIndicator(R.mipmap.ic_menu);
}
NavigationView navView= (NavigationView) findViewById(R.id.nav_view);
navView.setCheckedItem(R.id.nav_call);
navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener(){

@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {

switch (menuItem.getItemId()){
case R.id.nav_call:
Toast.makeText(MainActivity.this,"点击的是call",Toast.LENGTH_SHORT).show();
break;
case R.id.nav_mail:
Toast.makeText(MainActivity.this,"点击的是mail",Toast.LENGTH_SHORT).show();
break;
case R.id.nav_friends:
Toast.makeText(MainActivity.this,"点击的是friends",Toast.LENGTH_SHORT).show();
break;
case R.id.nav_location:
Toast.makeText(MainActivity.this,"点击的是location",Toast.LENGTH_SHORT).show();
break;
case R.id.nav_task:
Toast.makeText(MainActivity.this,"点击的是tast",Toast.LENGTH_SHORT).show();
break;

}
mDrawerLayout.closeDrawers();
return false;
}
});
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.backup:
Toast.makeText(this,"clicked BackUp",Toast.LENGTH_SHORT).show();
break;
case R.id.delete:
Toast.makeText(this,"clicked delete",Toast.LENGTH_SHORT).show();
break;
case R.id.action_settings:
Toast.makeText(this,"clicked action_settings",Toast.LENGTH_SHORT).show();
break;
case android.R.id.home:
mDrawerLayout.openDrawer(GravityCompat.START);
break;
}
return true;
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main,menu);
return true;
}
}

在主程序界面中,我们首先获得DrawerLayout的实例,然后调用getSupportActionBar()方法得到ActionBar的实例,虽然这个ActionBar是由Toolbar实现的(谷歌推荐后者取代前者了),接着调用ActionBar的setDisplayHomeAsUpEnabled()方法让导航按钮显示出来,又调用了setHomeAsUpIndicator()方法来设置一个导航按钮图标。实际上,Toolbar最左侧的这个按钮就叫做HomeAsUp,它默认的是一个返回的箭头,返回上一个活动。很明显,这里我们将它默认的样式和作用都进行了修改。

接下来在onOptionsItemSelected()方法中对HomeAsUp按钮的点击事件进行处理,HomeAsUp按钮的id是系统指定的,不变的,是android.R.id.home。然后调用DrawerLayout的openDrawer()方法将滑动菜单展示出来,注意openDrawer()方法需要传入一个Gravity参数,为了保证这里的行为和xml中定义的一致,我们传入的是GravityCompat.START。这样,在Toolbar的最左边就出现了一个导航按钮,这样用户看到按钮后就知道有菜单选项了,不然如果用户不滑动,还不知道有滑动菜单选项。

接下来是菜单选项方面的布局了,这里采用的是NavigationView控件,它也是Design Support库中的控件,使用它可以让菜单选项的实现变得更简单。

当然,由于是新特性,所以我们需要导入包,AS用户只需在app/build.gradle中的dependencies的闭包下添加如下几行就好了

compile 'com.android.support:design:23.1.0'
compile 'de.hdodenhof:circleimageview:2.1.0'
其中第一行是系统依赖包,第二个是看名字就知道是一个圆形的ImageView控件,使用它后,可以很方便的将图片变成圆角。

在使用Navagation的时候,我是将它设计的和QQ的类似,即上面是个头像和一些介绍,下面的是功能菜单选项。不过好像现在的滑动菜单大都是这样的。为此,需要2个布局文件,一个是头部的图片,一个下面的功能选项。

头部布局

headLayout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="180dp"
android:background="@color/colorPrimary"
android:padding="10dp">

<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_centerInParent="true"
android:src="@mipmap/nav_icon" />

<TextView
android:id="@+id/name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/mail_tv"
android:text="cmos"
android:textColor="#fff"
android:textSize="16sp" />

<TextView
android:id="@+id/mail_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="com.example@126.com"
android:textColor="#fff"
android:textSize="16sp" />
</RelativeLayout>
功能菜单选项布局采用的是menu.xml的配置的方式。为此,需要在res/menu文件夹下新建一个nav_menu.xml文件。

nav_menu.xml

<?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/nav_call"
android:icon="@mipmap/nav_call"
android:title="Call"></item>
<item
android:id="@+id/nav_friends"
android:icon="@mipmap/nav_friends"
android:title="friends"></item>
<item
android:id="@+id/nav_location"
android:icon="@mipmap/nav_location"
android:title="Location"></item>
<item
android:id="@+id/nav_task"
android:icon="@mipmap/nav_task"
android:title="Task"></item>
<item
android:id="@+id/nav_mail"
android:icon="@mipmap/nav_mail"
android:title="Mail"></item>
</group>
</menu>


上面的<menu>中嵌套的是一个<group>标签,然后将group的checkableBehavior属性指定为single,表示是每次选定一个。

建好两个子布局后,将其放置到NavigationView控件中。就是上面activity_main中app:menu和app:headerLayout两个属性指定的。这样就将菜单选项的布局设计好了。

说个题外话,

这里的Toolbar的最后面的按钮点击后会悬浮在标题栏上,这样做可能会挡住标题栏上的其他控件,也有可能挡住标题栏,为此,需要在style.xml文件中进行设置,将其设置为popwindow的样式。

style.xml

<resources>

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<!-- 窗口的样式 -->
<item name="actionOverflowMenuStyle">@style/MyMenuStyle</item>
</style>

<style name="MyMenuStyle" parent="@style/Widget.AppCompat.Light.PopupMenu.Overflow">
<item name="android:colorBackground">#696969</item>
<item name="overlapAnchor">false</item><!-- 是否覆盖overflow按钮,默认为true,即盖住Toolbar -->
<item name="android:popupBackground">?attr/colorPrimary</item><!--弹出菜单背景色为标题栏的背景色-->
<item name="android:dropDownVerticalOffset">0dip</item><!--弹出菜单与标题栏的垂直间距-->
</style>
</resources>
实现的后效果如下



点我下载源码

本文参考自郭神的《第一行代码 第2版》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: