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

Android侧滑控件DrawerLayout实战案例

2016-03-18 20:53 465 查看
Android v4包为开发者提供了一个侧滑控件DrawerLayout,使用起来也非常简单方便,省去了过去我们使用第三方库SlidingMenu之类的烦恼。

本篇博文主要是演示如何使用v4包下的侧滑控件DrawerLayout来现实一个可以左右侧滑的效果。(本案例在Eclipse下开发)

初识DrawerLayout真面目

(1)这个控件在v4包的 android.support.v4.widget包下。

android.support.v4.widget

|--DrawerLayout.class

说明:在Eclipse中创建项目,一般来自动在libs目录下包含v4支持包。

(2)DrawerLayout继承了ViewGroup,说明它是一个布局容器。

如果我们希望整个界面整体可以侧滑,我们可以把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>



在这个容器中我们可以添加内容界面布局(就是打开界面首先显示内容的那部分布局),左菜单界面布局,右菜单界面布局。

<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>

注意:布局时注意顺序,另外要给DrawerLayout布局加上一个id,以方便在代码中控制。而且实际项目开发中如果内容界面、左菜单界面或右菜单界面交互比较复杂的话可以分别使用Fragment来封装各自的逻辑,然后再把各自的Fragment嵌入到上面对应的布局中就可以了。

(3)DrawerLayout控制菜单打开与关闭的相关方法。

首先要在Activity的onCreate()方法中通过调用findViewById()把界面上的DrawerLayout获取到。

mDrawerL = (DrawerLayout) findViewById(R.id.dl_layout);

a)isDrawerOpen(int
gravity)


这个方法的作用是判断某菜单界面是否已经打开,返回一个boolean值 ,true代表已打开,false代表没有打开, 方法参数值可以是Gravity.LEFT(代表左菜单)或Gravity.RIGHT(代表右菜单)。

示例:

if(mDrawerL.isDrawerOpen(Gravity.LEFT)){
//判断左菜单是否打开,当然前提是布局中有左菜单界面,否则没有效果。
}


if(mDrawerL.isDrawerOpen(Gravity.RIGHT)){
//判断右菜单是否打开,当然前提是布局中有右菜单界面,否则没有效果。
}
b) openDrawer(int gravity)
这个方法的作用是打开某菜单,没有返回值,参数与上一个方法一样,用来指定左右菜单。

示例:

mDrawerL.openDrawer(Gravity.LEFT);//打开左菜单,前提是布局中有左菜单界面
mDrawerL.openDrawer(Gravity.RIGHT);//打开右菜单,前提是布局中有右菜单界面
c) closeDrawer(int gravity)
这个方法的作用是关闭某菜单,与openDrawer(int gravity)相针对。参数与上面方法一样,用来指定左右菜单。

示例:

mDrawerL.closeDrawer(Gravity.LEFT);//关闭左菜单,前提是布局中有左菜单界面

mDrawerL.closeDrawer(Gravity.RIGHT);//关闭右菜单,前提是布局中有右菜单界面

d) closeDrawers()

调用这个方法,可以一次性关闭所有菜单(左、右)。

e) setDrawerShadow(Drawable shadowDrawable, int gravity)

为某菜单添加投影效果,第一个参数是投影效果要使用的图片对象,第二个参数与上面方法一样。

f) addDrawerListener(DrawerListener
listener)


监听菜单的打开、关闭以及菜单切换状态变化,参数就是一个DrawerListener 监听器,一般通过匿名内部类实现。

示例:

mDrawerL.addDrawerListener(new DrawerListener() {

@Override
public void onDrawerStateChanged(int arg0) {
// 菜单切换状态变化时回调的方法

}

@Override
public void onDrawerSlide(View arg0, float arg1) {
// 菜单打开过程中不断回调的方法,第二个参数是菜单打开的偏移量值

}

@Override
public void onDrawerOpened(View arg0) {
// 菜单打开回调的方法,可以通过参数arg0判断打开的是哪个菜单

}

@Override
public void onDrawerClosed(View arg0) {
// 菜单关闭回调的方法,可以通过参数arg0判断关闭的是哪个菜单

}
});


案例实战

(1)效果





(2)布局

为了突出DrawerLayout,并没有使用Fragment之类的,所以布局这块比较简单,添加了内容界面布局(标题栏,左按钮,右按钮,其中引用了两张图片,可以换成自己任意喜欢的,并且因为自己提供了标题栏,所以记的把系统的标题栏去掉,),左菜单界面布局(按钮),右菜单界面布局(按钮)。需要注意的是在布局的时候如果根布局是DrawerLayout,在它里布局其它布局的时候很多布局或控件的属性的智能提示被屏蔽掉了。

解决办法:

根布局先不用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" >

<LinearLayout
android:id="@+id/ll_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@android:color/holo_blue_dark" >

<ImageButton
android:id="@+id/ib_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_margin="5dp"
android:background="@null"
android:src="@drawable/ic_account" />

<ImageButton
android:id="@+id/ib_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_margin="5dp"
android:background="@null"
android:src="@drawable/ic_star" />
</RelativeLayout>
</LinearLayout>

<RelativeLayout
android:id="@+id/rl_left_menu"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#ffffff" >

<ImageButton
android:id="@+id/ib_close_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@null"
android:src="@drawable/ic_launcher" />
</RelativeLayout>

<RelativeLayout
android:id="@+id/rl_right_menu"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:background="#ffffff" >

<ImageButton
android:id="@+id/ib_close_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@null"
android:src="@drawable/ic_launcher" />
</RelativeLayout>

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


(3)逻辑

按照上一步的布局,运行程序,左右滑动,看到已经可以实现左右滑动了,但是如果想要通过点击来切换内容界面,左菜单界面,右菜单界面,比如此时打开了左菜单,点击了左菜单的一个选项希望切换到内容界面显示,或此时在内容界面,想点击标题栏上的左按钮切换到左菜单。这些都需要对DrawerLayout进行逻辑控制,前面已经对常用的重要的逻辑控制方法用了介绍。通过它们就可以实现常用的交互逻辑了。当然为了使文章简单易性,还有一些方法没有介绍,比如addFocusables(ArrayList<View>views,
intdirection)可以让指定的控件获取焦addTouchables(ArrayList<View> views)可以让指定的控件可触摸,也就是触摸这些控件都可以使DrawerLayout侧滑。

当我们对DrawerLayout有了基本的认识后再学习这些方法会更好些。

package com.kedi.zhihuribao.activity;

import com.kedi.zhihuribao.R;

import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.Toast;

/**
* 主界面Activity
*
* @author 张科勇
这里的Activity继承了AppCompatActivity 使用到了v7包,需要提前导入并依赖该库。这是个版本兼容库。
注意点:
* (1)导入的时候一定要选中copytoworkspace, 否则会因为库目录和项目目录不一致而依赖不成功
* (2)创建项目的时候,配置最低版本号在4.0以下时,v7库会随着项目的创建被导入进来,也就是创建引程序会检查一次版本兼    容问题。 但是如果最低版本号高于4.0,创建引导程序不会检查兼容问题,所以也不会 把v4库一起导入进来。
*
技术点:
(1)侧滑控件android.support.v4.widget.DrawerLayout
*
*         布局分为:
a)内容布局:正常布局
b)左菜单布局:正常布局+(android:layout_gravity ="start|left")左对齐控制
c)右菜单布局:正常布局+(android:layout_gravity = "end|right")右对齐控制 注意:先各自加上不同的背景以示 区别,观看效果。
*
*/
public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawerL;
private ImageButton mLeftIb;
private ImageButton mRightIb;
private ImageButton mCloseLeftIb;
private ImageButton mCloseRightIb;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
setListener();
}

/**
* 初始化控件的方法
*/
private void initView() {
mDrawerL = (DrawerLayout) findViewById(R.id.dl_layout);
mLeftIb = (ImageButton) findViewById(R.id.ib_left);
mRightIb = (ImageButton) findViewById(R.id.ib_right);
mCloseLeftIb =(ImageButton) findViewById(R.id.ib_close_left);
mCloseRightIb=(ImageButton) findViewById(R.id.ib_close_right);
}
/**
* 注册事件监听器
*/
private void setListener(){

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);
}
}
});
mRightIb.setOnClickListener(new OnClickListener() {

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

}
});
mCloseLeftIb.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
//判断左菜单是否已打开 ,如果是,则关闭左菜单
if(mDrawerL.isDrawerOpen(Gravity.LEFT)){
mDrawerL.closeDrawer(Gravity.LEFT);
}

}
});
//判断右菜单是否已打开 ,如果是,则关闭右菜单
mCloseRightIb.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {

if(mDrawerL.isDrawerOpen(Gravity.RIGHT)){
mDrawerL.closeDrawer(Gravity.RIGHT);
}

}
});
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: