Android Moveview滑屏移动视图类完整实例
本文示例所述程序为一个AndroidMoveview移动视图类。其主要实现主屏左右滑屏拖动功能,并适时显示拖动时候屏幕的显示情况,该代码中还包括完整的逻辑。其完整代码如下:
importandroid.study.shift.ItemView; importandroid.study.shift.MainView; importandroid.study.shift.Moveview; importandroid.content.Context; importandroid.os.Handler; importandroid.os.Message; importandroid.util.AttributeSet; importandroid.util.Log; importandroid.view.MotionEvent; importandroid.view.View; importandroid.view.ViewGroup; importandroid.view.View.MeasureSpec; publicclassMoveviewextendsViewGroup{ privatefinalstaticintTOUCH_STATE_REST=0; privatefinalstaticintTOUCH_STATE_MOVING=1; privatefinalstaticintMOVE_TO_LEFT=1; //privatefinalstaticintMOVE_TO_RIGHT=2; privatefinalstaticintMOVE_TO_REST=0; publicfinalstaticintMAIN=0; publicfinalstaticintLEFT=1; publicfinalstaticintRIGHT=2; privateinttouch_state=TOUCH_STATE_REST; privateintmove_state=MOVE_TO_REST; privateintnow_state=MAIN; privatefinalfloatWIDTH_RATE=0.18f; privateMainViewmain_show_view; privateItemViewleft_show_view; privateintmin_distance=30;//此处只是初始化为30,其实不起作用 privateintscreen_w; privateintscreen_h; privateintmove_x_v; privatebooleanisAimationMoving=false; privateHandlermHandler=newHandler(){ publicvoidhandleMessage(Messagemsg){//处理消息 synchronized(Moveview.this){//同步 isAimationMoving=true; intmove_change=(int)(screen_w*WIDTH_RATE/5); intleft=main_show_view.getView().getLeft(); if(msg.what==1){//主屏在向右拖曳。。。 move(move_change+left);//参数为拖出来后主屏的坐标。 } if(msg.what==11){ isAimationMoving=false; moveToLeft(false);//满足可以显示的要求开始显示,false只是一个判定条件,以区别按钮起的效果 } if(msg.what==2){//代表主屏向左在拖曳。。。 move(-1*move_change+left); } if(msg.what==12){ isAimationMoving=false; //moveToRight(false); } if(msg.what==0){ if(now_state==LEFT){//如果现在已经显示左边 move(-1*move_x_v);//那么还原成主屏 }else{ move(move_x_v); } } if(msg.what==10){ isAimationMoving=false; moveToMain(false); } } } }; publicMoveview(Contextcontext){ super(context); } publicMoveview(Contextcontext,AttributeSetattrs){ super(context,attrs); } publicMoveview(Contextcontext,AttributeSetattrs,intdefStyle){ super(context,attrs,defStyle); } publicvoidinitView(){ if(main_show_view==null){ main_show_view=newMainView(this.getContext(),this); left_show_view=newItemView(this.getContext()); //right_show_view=newItemView(this.getContext(),"aaa"); } this.addView(left_show_view.getView()); //this.addView(right_show_view.getView()); this.addView(main_show_view.getView()); } publicvoidinitContent(){ } publicvoidmove(intstart){//本函数显示拖动的时候屏幕的显示情况。 intleft=main_show_view.getView().getLeft();//left代表主屏左边缘的位置坐标。 if(now_state==MAIN){ if(left>0){//如果屏幕的左边被移向右,则left变成正数 if(move_state!=MOVE_TO_LEFT){ move_state=MOVE_TO_LEFT; } left_show_view.getView().setVisibility(View.VISIBLE);//设置左边可见 //right_show_view.getView().setVisibility(View.GONE); }//elseif(left<0){//如果屏幕的左边被移向左,则left变成负数 //if(move_state!=MOVE_TO_RIGHT){ //move_state=MOVE_TO_RIGHT; //} //right_show_view.getView().setVisibility(View.VISIBLE); //left_show_view.getView().setVisibility(View.GONE); //} else{ move_state=MOVE_TO_REST; } main_show_view.getView().layout(start,0,start+screen_w, screen_h);//参数依次为左、上、右、下。 }else{ left=(int)(screen_w*WIDTH_RATE);//left为左边应该留出的控件空间,或者主屏左边应该在的位置 if(now_state==RIGHT){ left=-1*left;//若状态是在右边空出来,则主屏的左边为负数 } left=left+start; main_show_view.getView().layout(left,0,left+screen_w,screen_h); } } @Override protectedvoidonLayout(booleanarg0,intarg1,intarg2,intarg3,intarg4){ if(move_state==MOVE_TO_REST){ if(now_state==MAIN){ intw=(int)(screen_w*WIDTH_RATE);//留下预定的宽度,显示各个view的参数设置。 main_show_view.getView().layout(0,0,screen_w,screen_h); left_show_view.getView().layout(0,0,w,screen_h); }elseif(now_state==LEFT){ moveToLeft(false); }else{ } } } protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){ main_show_view.getView().measure(widthMeasureSpec,heightMeasureSpec); left_show_view.getView().measure(MeasureSpec.UNSPECIFIED,//unspecified为未指定的 heightMeasureSpec); left_show_view.setWidth((int)(screen_w*WIDTH_RATE));//设置view宽度 super.onMeasure(widthMeasureSpec,heightMeasureSpec);//调用父类的构造函数 } privateintstart_x; privateintstart_y; privatebooleanisMoved; publicbooleandispatchTouchEvent(MotionEventev){//分发触摸消息事件 if(isAimationMoving){ returnsuper.dispatchTouchEvent(ev); }else{ intaction=ev.getAction(); floatx=ev.getX(); floaty=ev.getY(); switch(action){ caseMotionEvent.ACTION_DOWN: super.dispatchTouchEvent(ev); start_y=(int)y; move_x_v=0; if(this.touch_state==TOUCH_STATE_REST){ this.touch_state=TOUCH_STATE_MOVING; start_x=(int)x; isMoved=false; move_state=MOVE_TO_REST; } break; caseMotionEvent.ACTION_MOVE: intlast_y=(int)y; intlast_x=(int)x; super.dispatchTouchEvent(ev); if(!isMoved){ if(Math.abs(last_y-start_y)>Math.abs(last_x-start_x)){//如果Y上面移动的距离大于X上面移动的距离。 super.onTouchEvent(ev); returntrue; }else{//X移动距离大于Y if(Math.abs(last_x-start_x)>5){//X移动距离大于5就被认为移动了 isMoved=true; } } } if(isMoved){ if(this.touch_state==TOUCH_STATE_MOVING){ if(Math.abs(last_x-start_x)>10){//如果移动的X距离大于10 intleft=main_show_view.getView().getLeft(); Log.d("msg","left:"+left); Log.d("msg","x:"+last_x); isMoved=true; intmove_x=last_x-start_x; if(move_x>0&&now_state==LEFT){//方向正确的移动才算是移动的状态 isMoved=false; break; } if(move_x<0&&now_state==RIGHT){//如果现在在显示右边,那么再向右移就不反应。 isMoved=false; break; } if(move_x<0&&now_state==MAIN){//如果现在在主屏,向右移动也是无效的 isMoved=false; break; } if(move_x>234&&now_state==MAIN){ isMoved=true;//设置为true那么移动还是发生了,break之后还是会在ACTIONUP中起作用 break;//break之后不会执行下面的move()语句, } if(move_x<-234&&now_state==LEFT){ isMoved=true; break; } move(move_x);//以移动的距离为参数调用move()实现移动的动态显示 } } returnfalse; } break; caseMotionEvent.ACTION_UP:// if(this.touch_state==TOUCH_STATE_MOVING){ if(isMoved){ last_x=(int)x; if(Math.abs(last_x-start_x)>min_distance){// if(now_state==MAIN){ if(move_state==MOVE_TO_LEFT){ this.moveToLeft(false); } }else{ this.moveToMain(false); } }else{// if(now_state==MAIN){ this.moveToMain(false); } if(now_state==LEFT){ this.moveToLeft(false); } if(now_state==RIGHT){ //this.moveToRight(false); } } move_state=MOVE_TO_REST; }else{ super.dispatchTouchEvent(ev); this.touch_state=TOUCH_STATE_REST; returnfalse;// } } super.onTouchEvent(ev); this.touch_state=TOUCH_STATE_REST; break; } returntrue; } } publicbooleangetIsMoved(){ returnisMoved; } publicvoidmoveToLeft(booleanb){ if(!b){ intmove_x=(int)(screen_w*WIDTH_RATE); left_show_view.getView().layout(0,0,screen_w,screen_h); //right_show_view.getView().layout(move_x,0,move_x*2,screen_h); main_show_view.getView().layout(move_x,0,move_x+screen_w, screen_h); now_state=LEFT;//为什么现在又把now_state赋值为left? } //else{//else以及括号中的语句都是为原来的按钮准备的。。。 //mHandler.postDelayed(newRunnable(){//一个新的可运行的函数 // //@Override //publicvoidrun(){ //intmove_change=(int)(screen_w*WIDTH_RATE/5);//五分之一要显示的宽度 //intleft=(int)(screen_w*WIDTH_RATE-main_show_view //.getView().getLeft());//getleft()返回的是主屏左边缘离左边的距离 //Messagemsg=newMessage(); //if(left>move_change){//括号里面不懂,起什么作用? //msg.what=1; //mHandler.sendMessage(msg); //mHandler.postDelayed(this,10);//又调用自己,基本上非要是小于关系 //}else{ //msg.what=11; //mHandler.sendMessage(msg); //mHandler.removeCallbacks(this); //} //} //},0); //} } publicvoidmoveToMain(booleanb){ if(!b){ //right_show_view.getView().setVisibility(View.VISIBLE); left_show_view.getView().setVisibility(View.VISIBLE); intw=(int)(screen_w*WIDTH_RATE); main_show_view.getView().layout(0,0,screen_w,screen_h); left_show_view.getView().layout(0,0,w,screen_h); now_state=MAIN; } } publicvoidinitScreenSize(intw,inth){ this.screen_w=w; this.screen_h=h; Log.d("screen","screen_w:"+w); this.setKeepScreenOn(true); min_distance=(int)(screen_w/12.0);//min_distance在这里又被初始化为屏幕的一个比例大小 initView(); initContent(); moveToMain(false); } publicintgetNowState(){ returnthis.now_state; } }