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

Android:可动态布局抽屉之完整篇

2014-08-09 23:39 239 查看
本文来自http://blog.csdn.net/hellogv/ ,欢迎转摘,引用必须注明出处!

上次介绍了基础篇,讲解了自定义抽屉控件的基础实现,这次就在基础篇的基础上加入拖拉功能。拖拉功能基于GestureDetector,GestureDetector的基本使用方式不是本文介绍的重点,有兴趣的童鞋可以上网查询相关的教程。

本文的抽屉控件相对于基础篇的抽屉控件多了以下功能:

1.支持手势拖拉

2.拖拉到一半时,可以自动展开或者收缩。

具体如下图:




本文的源码可以到这里下载:http://download.csdn.net/detail/hellogv/3642418

只贴出抽屉组件的源码,其他源文件与基础篇的一样:

[java] view
plaincopyprint?

<span style="font-family:Comic Sans MS;font-size:18px;">public class Panel extends LinearLayout implements GestureDetector.OnGestureListener{



public interface PanelClosedEvent {

void onPanelClosed(View panel);

}



public interface PanelOpenedEvent {

void onPanelOpened(View panel);

}



private final static int HANDLE_WIDTH=30;

private final static int MOVE_WIDTH=20;

private Button btnHandler;

private LinearLayout panelContainer;

private int mRightMargin=0;

private Context mContext;

private GestureDetector mGestureDetector;

private boolean mIsScrolling=false;

private float mScrollX;

private PanelClosedEvent panelClosedEvent=null;

private PanelOpenedEvent panelOpenedEvent=null;



public Panel(Context context,View otherView,int width,int height) {

super(context);

this.mContext=context;



//定义手势识别

mGestureDetector = new GestureDetector(mContext,this);

mGestureDetector.setIsLongpressEnabled(false);



//改变Panel附近组件的属性

LayoutParams otherLP=(LayoutParams) otherView.getLayoutParams();

otherLP.weight=1;

otherView.setLayoutParams(otherLP);



//设置Panel本身的属性

LayoutParams lp=new LayoutParams(width, height);

lp.rightMargin=-lp.width+HANDLE_WIDTH;

mRightMargin=Math.abs(lp.rightMargin);

this.setLayoutParams(lp);

this.setOrientation(LinearLayout.HORIZONTAL);



//设置Handler的属性

btnHandler=new Button(context);

btnHandler.setLayoutParams(new LayoutParams(HANDLE_WIDTH,height));

//btnHandler.setOnClickListener(handlerClickEvent);

btnHandler.setOnTouchListener(handlerTouchEvent);

this.addView(btnHandler);



//设置Container的属性

panelContainer=new LinearLayout(context);

panelContainer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,

LayoutParams.FILL_PARENT));

this.addView(panelContainer);



}



private View.OnTouchListener handlerTouchEvent=new View.OnTouchListener() {



@Override

public boolean onTouch(View v, MotionEvent event) {

if(event.getAction()==MotionEvent.ACTION_UP && //onScroll时的ACTION_UP

mIsScrolling==true)

{

LayoutParams lp=(LayoutParams) Panel.this.getLayoutParams();

if (lp.rightMargin >= (-mRightMargin/2)) {//往左超过一半

new AsynMove().execute(new Integer[] { MOVE_WIDTH });// 正数展开

}

else if (lp.rightMargin < (-mRightMargin/2)) {//往右拖拉

new AsynMove().execute(new Integer[] { -MOVE_WIDTH });// 负数收缩

}

}

return mGestureDetector.onTouchEvent(event);

}

};



/**

* 定义收缩时的回调函数

* @param event

*/

public void setPanelClosedEvent(PanelClosedEvent event)

{

this.panelClosedEvent=event;

}



/**

* 定义展开时的回调函数

* @param event

*/

public void setPanelOpenedEvent(PanelOpenedEvent event)

{

this.panelOpenedEvent=event;

}



/**

* 把View放在Panel的Container

* @param v

*/

public void fillPanelContainer(View v)

{

panelContainer.addView(v);

}



/**

* 异步移动Panel

* @author hellogv

*/

class AsynMove extends AsyncTask<Integer, Integer, Void> {



@Override

protected Void doInBackground(Integer... params) {

int times;

if (mRightMargin % Math.abs(params[0]) == 0)// 整除

times = mRightMargin / Math.abs(params[0]);

else

// 有余数

times = mRightMargin / Math.abs(params[0]) + 1;



for (int i = 0; i < times; i++) {

publishProgress(params);

try {

Thread.sleep(Math.abs(params[0]));

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

return null;

}



@Override

protected void onProgressUpdate(Integer... params) {

LayoutParams lp = (LayoutParams) Panel.this.getLayoutParams();

if (params[0] < 0)

lp.rightMargin = Math.max(lp.rightMargin + params[0],

(-mRightMargin));

else

lp.rightMargin = Math.min(lp.rightMargin + params[0], 0);



if(lp.rightMargin==0 && panelOpenedEvent!=null){//展开之后

panelOpenedEvent.onPanelOpened(Panel.this);//调用OPEN回调函数

}

else if(lp.rightMargin==-(mRightMargin) && panelClosedEvent!=null){//收缩之后

panelClosedEvent.onPanelClosed(Panel.this);//调用CLOSE回调函数

}

Panel.this.setLayoutParams(lp);

}

}



@Override

public boolean onDown(MotionEvent e) {

mScrollX=0;

mIsScrolling=false;

return false;

}



@Override

public boolean onSingleTapUp(MotionEvent e) {

LayoutParams lp = (LayoutParams) Panel.this.getLayoutParams();

if (lp.rightMargin < 0)// CLOSE的状态

new AsynMove().execute(new Integer[] { MOVE_WIDTH });// 正数展开

else if (lp.rightMargin >= 0)// OPEN的状态

new AsynMove().execute(new Integer[] { -MOVE_WIDTH });// 负数收缩

return false;

}



@Override

public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,

float distanceY) {

mIsScrolling=true;

mScrollX+=distanceX;



LayoutParams lp=(LayoutParams) Panel.this.getLayoutParams();

if (lp.rightMargin < -1 && mScrollX > 0) {//往左拖拉

lp.rightMargin = Math.min((lp.rightMargin + (int) mScrollX),0);

Panel.this.setLayoutParams(lp);

Log.e("onScroll",lp.rightMargin+"");

}

else if (lp.rightMargin > -(mRightMargin) && mScrollX < 0) {//往右拖拉

lp.rightMargin = Math.max((lp.rightMargin + (int) mScrollX),-mRightMargin);

Panel.this.setLayoutParams(lp);

}



if(lp.rightMargin==0 && panelOpenedEvent!=null){//展开之后

panelOpenedEvent.onPanelOpened(Panel.this);//调用OPEN回调函数

}

else if(lp.rightMargin==-(mRightMargin) && panelClosedEvent!=null){//收缩之后

panelClosedEvent.onPanelClosed(Panel.this);//调用CLOSE回调函数

}

Log.e("onScroll",lp.rightMargin+"");



return false;

}



@Override

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,

float velocityY) {return false;}

@Override

public void onLongPress(MotionEvent e) {}

@Override

public void onShowPress(MotionEvent e) {}



}

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