抽屉效果,顾名思义就是可以像抽屉一样拉出来推进去,在Android中一般是通过滑动(从左到右,或者像帘子一样从上往下拉,或者通过某个按钮)来实现抽屉效果。其实Android的抽屉效果很简单(V4.0以上),使用了一个叫做DrawerLayout的类就可以轻松实现。废话少说,开始干活。
Android官网的教程(需要翻墙):http://developer.android.com/training/implementing-navigation/nav-drawer.html
首先说说我今天准备实现的目标:
1、抽屉效果,就是可以推拉的,这个是基本(我的是从左向右滑动)。
2、挤压效果。所谓挤压,就是当把抽屉拉出来是,原来的屏幕不会被遮挡或者覆盖,而是顺势向同样的方向移动相同的距离。之所以会做这一个效果,是因为官网的DrawerLayout是默认会挤压的。
效果如下图(由于不知道怎么手机动态截屏,只能上静态图了,有知道的可以告诉我,当然腾讯手机管家的试过了,不流畅)
下面是具体的实现步骤
1、布局文件mlayout.xml
需要注意的是:
(1)这里的根标签是android.support.v4.widget.DrawerLayout而不是普通的RelativeLayout之类的,里面有2个部分,第一个部分是The main content view,主界面,也就是抽屉还没打开之前的界面,这里官网用的是FrameLayout,其实也就是一个主界面的布局,所以都无所谓,我喜欢用RelativeLayout所以用它,主界面布局内根据自己的需要随意添加空间;
(2)第二个部分就是抽屉的界面,布局也是随意的。我用的是ListView,因为一般拉出来的抽屉,都是系统的一些设置和检查更新什么的。
(3)主界面布局宽和高,必须match_parent,抽屉的高也是,抽屉的宽度不得超过320dp(官方规定的),否则会全部遮挡(或挤压)掉主布局。
(4)抽屉有个属性是layout_gravity,这个是指抽屉出来的方向,必须设置。一般可以设置left、end、right、start(不过貌似我出来start,其他的感觉都会使应用崩溃)
2、主类MainActivity.java,其中滑动和点击按钮都可以打开抽屉
package com.exam.drawerdemo;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.DrawerLayout.DrawerListener;
import android.view.Gravity;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.RelativeLayout;
public class MainActivity extends Activity {
DrawerLayout mDrawerLayout;
Button mButton;
ListView mDrawerList;
String[] str={"AA","BB","CC","DD","EE","FF"};
RelativeLayout mRelativeLayout;
int mDrawerWidth;//抽屉全部拉出来时的宽度
float scrollWidth;//抽屉被拉出部分的宽度
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mlayout);
mDrawerLayout=(DrawerLayout)findViewById(R.id.drawer_layout);
mRelativeLayout=(RelativeLayout) findViewById(R.id.content_frame);
//填充抽屉ListView的内容
mDrawerList=(ListView)findViewById(R.id.left_drawer);
mDrawerList.setAdapter(new ArrayAdapter(getApplicationContext(),
android.R.layout.simple_expandable_list_item_1,str));
//测量抽屉的宽度和高度
measureView(mDrawerList);
mDrawerWidth=mDrawerList.getMeasuredWidth();
mButton=(Button)findViewById(R.id.mButton);
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mDrawerLayout.openDrawer(Gravity.LEFT);
}
});
//必须给抽屉设置监听事件
mDrawerLayout.setDrawerListener(new DrawerListener() {
@Override
public void onDrawerStateChanged(int arg0) {
}
//抽屉被拉出来或者推回去
@Override
public void onDrawerSlide(View arg0, float arg1) {
//因为arg1的范围是0.0-1.0,是一个相对整个抽屉宽度的比例
//所以要准换成
scrollWidth=arg1*mDrawerWidth;
//setScroll中的参数,正数表示向左移动,负数向右
mRelativeLayout.setScrollX((int)(-1*scrollWidth));
}
@Override
public void onDrawerOpened(View arg0) {
}
@Override
public void onDrawerClosed(View arg0) {
}
});
}
/**
* 此方法可以多次被不同的View对象调用。
* 在调用该方法后,
* 使用View对象的getMessuredHeight()获高度(单位px)
* @param child 需要测量高度和宽度的View对象,
*/
private void measureView(View child) {
ViewGroup.LayoutParams params = child.getLayoutParams();
if (params == null) {
params = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0,
params.width);
int lpHeight = params.height;
int childHeightSpec;
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
}
}
再啰嗦几句:(1)挤压效果的实现,其实就是通过监测抽屉向右滑动的距离,然后主界面也通过滑动相应距离实现的(setScroll,负数表示向右);(2)DrawerLayout有个方法openDrawer(Gravity arg)也可以打开抽屉,其关闭则是closeDrawer();但是用了按钮打开抽屉(比如我上面的),不影响滑动也可以打开。
有问题和建议的,或者如上面说的有比较好的动态截屏方法的,欢迎再下面留言
源码地址:http://download.csdn.net/detail/programming2012/8554275