实现效果:

上一篇写了关于图形相关绘制:
http://www.jianshu.com/p/25aa4789b3fd
关于动画方面,主要分两个方面:
一、圆圈拉伸的动画。
1 、圆被拉出去时的动画
2、圆拉伸后缩回去的动画
二、在加载时中心圆弧的动画
1、圆被拉伸出去时的动画
首先是记录下手指按下的点的坐标downPoint,然后是手指滑动后停留的点movePoint。并调用invalidate()让view根据两点的状态重新绘制。这样就实现圆随手指滑动而拉伸的动画
并且在此判断滑动的距离是否触发回滚动画
case MotionEvent.ACTION_DOWN:
if(!stickyAnimator.isRunning() && !loadAnimator.isRunning()){
downPoint.x = x;
downPoint.y = y;
movePoint.set(downPoint);
resetLoadAnimator();
}
break;
case MotionEvent.ACTION_MOVE:
if(!stickyAnimator.isRunning() && !loadAnimator.isRunning() && !loading){
movePoint.x = x;
movePoint.y = y;
float distanceMove = getDistanceBetweenTwoPoints(downPoint.x,downPoint.y,movePoint.x,movePoint.y);
//滑动距离在动作范围内,则开始执行回滚动画和loading动画
if(inLoadArea(distanceMove)){
loading = true;
executeAnimator(distanceMove);
}
invalidate();
}
break;
2、圆形缩回的动画
除了在手指滑动距离超过一定范围后触发,在手指离开屏幕时也会触发
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if(!stickyAnimator.isRunning() && !loadAnimator.isRunning() && !loading){
movePoint.x = x;
movePoint.y = y;
float distanceUp = getDistanceBetweenTwoPoints(downPoint.x,downPoint.y,movePoint.x,movePoint.y);
//滑动距离在动作范围内,则开始执行回滚动画和loading动画,否则只开始回滚动画
if(inLoadArea(distanceUp)){
loading = true;
}
executeAnimator(distanceUp);
}
break;
回滚的动画,其实就是手指最后离开的点movePoint沿着直线移动到当初按下的点downPoin的过程。就是movePoint和downPoin两点的距离distance逐渐变为0的过程,根据distance的变化,可以计算回来movePoint的变化的一系列坐标。按上一篇的介绍,图形的绘制会根据downPoint和movePoint的值来绘制,这样每次movePoint得到新值后,重新绘制就可以实现动画
初始化的时候就可以设置好动画的参数,StickyAnimator就是负责执行缩回动画的
//这里先不给animator设置evaluator,因为暂时还不知道需要变化的值,此时设置了也无效
evaluator = new FloatEvaluator();
stickyAnimator = new ValueAnimator();
//设置插值器
stickyAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
//设置属性值变化的监听,这里得到的newDistance就是两点新的距离
stickyAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float newDistance = (float) animation.getAnimatedValue();
float distance = getDistanceBetweenTwoPoints(downPoint.x,downPoint.y,movePoint.x,movePoint.y);
float cos = (movePoint.x - downPoint.x)/distance;
float sin = (movePoint.y - downPoint.y)/distance;
movePoint.x = downPoint.x + newDistance * cos;
movePoint.y = downPoint.y + newDistance * sin;
invalidate();
}
});
//圆形缩回来后判断是否需要执行loading动画
stickyAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
//在onTouchEvent里面判断了移动的距离是否触发加载动画
if(loading){
loadAnimator.start();
if(mReloadListener != null) mReloadListener.onReload();
}
}
});
在onTouchEvent()方法里面判断执行的时机,并且获取动画需要变化的值
private boolean inLoadArea(float distance){
return distance <= MaxMoveDistance*0.75 && distance >= MaxMoveDistance * 0.33;
}
private void executeAnimator(float distance){
//两个圆重合时无需回滚
if(distance == 0) return;
stickyAnimator.setObjectValues(distance,0);
stickyAnimator.setEvaluator(evaluator);
stickyAnimator.setDuration(STICKY_DURATION);
stickyAnimator.start();
}
3、加载动画的实现
触发加载动画后,mLoadAnimatorValue的值由0到1,然后再绘制的时候根据这个值计算出截取圆弧的部分
loadAnimator = ValueAnimator.ofFloat(0,1).setDuration(LOADING_DURATION);
loadAnimator.setRepeatCount(-1);//loading动画一直执行,直到调用cancel()后才停止
loadAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mLoadAnimatorValue = (float) animation.getAnimatedValue();
invalidate();
}
});
private void drawLoading(Canvas canvas){
//基本和绘制一般状态的时候一样,除了截取的起点和终点需要动态的计算
canvas.save();
canvas.translate(circleStart.centerPoint.x, circleStart.centerPoint.y);
canvas.scale(1 - mScale,1 - mScale);
pathMeasure.setPath(mLoadPath,false);
Path newPath = new Path();
float stop = pathMeasure.getLength() * mLoadAnimatorValue;
float start = (float)(stop - (0.5 - Math.abs(mLoadAnimatorValue - 0.5)) * 200f);
pathMeasure.getSegment(start,stop,newPath,true);
canvas.drawPath(newPath, mLoadPaint);
canvas.restore();
}
当loading动画会一直执行直到调用cancel()方法才停止。当所有动画都停止后,在手指按下屏幕的时候,重置一下状态
case MotionEvent.ACTION_DOWN:
if(!stickyAnimator.isRunning() && !loadAnimator.isRunning()){
downPoint.x = x;
downPoint.y = y;
movePoint.set(downPoint);
resetLoadAnimator();
}
break;
网友评论