android粘性控件,[Android开发]仿带有粘性的圆形刷新控件(2)

实现效果:

5d35e37ef02a

关于动画方面,主要分两个方面:

一、圆圈拉伸的动画。

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;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值