本文来自http://blog.csdn.net/hellogv/ ,欢迎转摘,引用必须注明出处!
上次介绍了基础篇,讲解了自定义抽屉控件的基础实现,这次就在基础篇的基础上加入拖拉功能。拖拉功能基于GestureDetector,GestureDetector的基本使用方式不是本文介绍的重点,有兴趣的童鞋可以上网查询相关的教程。
本文的抽屉控件相对于基础篇的抽屉控件多了以下功能:
1.支持手势拖拉
2.拖拉到一半时,可以自动展开或者收缩。
具体如下图:
本文的源码可以到这里下载:http://download.csdn.net/detail/hellogv/3642418
只贴出抽屉组件的源码,其他源文件与基础篇的一样:
- <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>