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;
}
}