用FrameLayout加OnToucherListener制作View切换动画

来源:互联网 发布:新装办公室网络布线 编辑:程序博客网 时间:2024/05/17 03:07

初学Android,由于只了解一些常见的View和布局,所以在做APP的过程中受到了很多限制,在经过对网上一些demo的参考之后,自己总结出可以通过FrameLayout加OnTouchListener编写出多种简单的切换效果。

左图为没有切换动画时的界面,右图为view切换的界面,切换过程中切换动画会随着手指的滑动而滑动,当手指离开屏幕,某一个view会有动画重新占满全屏。

首先分析一下流程:手指触摸屏幕(ACTION_DOWN)->手指移动(ACTION_MOVE)->手指离开屏幕(ACTION_UP)->view自动充满屏幕

手指触摸屏幕:当手指触摸屏幕时,我们可以获取一个ACTION_DOWN事件,这个时候需要记录下当前的X坐标

<span style="white-space:pre"></span>case MotionEvent.ACTION_DOWN://获取最初点坐标的XpreX = event.getX();break;

手指移动:当手指在屏幕上滑动时,我们可以持续获得一系列的ACTION_MOVE事件,通过当前事件的X坐标与ACTION_DOWN事件X坐标的差可以计算出当前的偏移量

<span style="white-space:pre"></span>case MotionEvent.ACTION_MOVE://获取当前view的偏移量offset = event.getX() - preX;

根据偏移量,计算出当前偏移占屏幕宽度的比例,这个比例用于缩放view以及改变view的透明度

<span style="white-space:pre"></span>/** * 获取view偏移相对于屏幕宽度的比例 */float scaleOffset = Math.abs(offset)/viewWidth;/** * 当偏于比例大于最小偏移比例时,根据偏移比例缩放view;当偏移到一定程度时,view不再缩小 */float scaleFactor = Math.max(MIN_SCALE, Math.max(1 - scaleOffset, scaleOffset));/** * 设定view的透明度 */float alpha = 0.4f+0.4f*(1-scaleFactor);float scaleAlpha = offset == 0 ? 1: alpha;

然后就根据比例缩放view,根据偏移量移动view

<span style="white-space:pre"></span>currentView.setScaleX(scaleFactor);        currentView.setScaleY(scaleFactor);        currentView.setAlpha(scaleAlpha);        currentView.setTranslationX(offset);        nextView.setScaleX(scaleFactor);        nextView.setScaleY(scaleFactor);        nextView.setAlpha(scaleAlpha);        nextView.setTranslationX(offset);        lastView.setScaleX(scaleFactor);        lastView.setScaleY(scaleFactor);        lastView.setAlpha(scaleAlpha);        lastView.setTranslationX(offset);
手指离开屏幕:当手指离开屏幕时,这个时候会获取到一个ACTION_UP事件,获取到这个事件时,我们就要判断是否切换当前view,我判断的标准是是否滑动超过屏幕的1/2

<span style="white-space:pre"></span>case MotionEvent.ACTION_UP://离开屏幕时根据偏移量判断是否切换viewif(offset > viewWidth/2){handler.sendEmptyMessage(TO_RIGHT);}else if(offset < -viewWidth/2){handler.sendEmptyMessage(TO_LEFT);}else {handler.sendEmptyMessage(TO_CENTRE);}
view自动充满屏幕:当经过判断之后,如果滑动没有超过屏幕的1/2,那就让原来的view按照原来的路径从新充满屏幕;如果没有那就让下一个view按照进入屏幕的方向移动充满屏幕。充满屏幕这个过程,我是选用用Handler延时发送消息的方式进行的,当然也可以采用线程睡眠的方式。

<span style="white-space:pre"></span>@Overridepublic void handleMessage(Message message){super.handleMessage(message);Context context = this.context.get();if(context != null){switch(message.what){case TO_CENTRE:if(offset < 0 ){offset = offset + 30;}else{offset = offset - 30;}drawView(offset);if(Math.abs(offset)<30){offset = 0;drawView(offset);}else{sendEmptyMessageDelayed(TO_CENTRE, 5);}break;case TO_LEFT:offset = offset - 30;if(offset > -viewWidth){drawView(offset);sendEmptyMessageDelayed(TO_LEFT, 5);}else{offset = 0;initOrder(viewCentre, viewRight, viewLeft);drawView(offset);viewLeft = (viewLeft + 1) % 3;viewCentre = (viewCentre + 1) % 3;viewRight = (viewRight + 1) % 3;}break;case TO_RIGHT:offset = offset + 30;if(offset < viewWidth){drawView(offset);sendEmptyMessageDelayed(TO_RIGHT, 5);}else{offset = 0;initOrder(viewRight, viewLeft, viewCentre);drawView(offset);viewLeft = (viewLeft + 2) % 3;viewCentre = (viewCentre + 2) % 3;viewRight = (viewRight + 2) % 3;}break;default:break;}}}
Demo下载地址






0 0
原创粉丝点击