本文来自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);???
- ????????}??
- ????};??
- ??
- ????/**?
- ?????*?定义收缩时的回调函数?
- [email protected]?
- ?????*/??
- ????public?void?setPanelClosedEvent(PanelClosedEvent?event)??
- ????{??
- ????????this.panelClosedEvent=event;??
- ????}??
- ??????
- ????/**?
- ?????*?定义展开时的回调函数?
- [email protected]?
- ?????*/??
- ????public?void?setPanelOpenedEvent(PanelOpenedEvent?event)??
- ????{??
- ????????this.panelOpenedEvent=event;??
- ????}??
- ??????
- ????/**?
- ?????*?把View放在Panel的Container?
- [email protected]?
- ?????*/??
- ????public?void?fillPanelContainer(View?v)??
- ????{??
- ????????panelContainer.addView(v);??
- ????}??
- ??????
- ????/**?
- ?????*?异步移动Panel?
- [email protected]?
- ?????*/??
- ????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>??
?