安卓自定义动画——画一个圆和对勾
2015-11-17 08:14
393 查看
与支付宝支付成功后类似的一个动画,本人小白一只大神请绕过,画的菜大家见谅
直接将view拷贝进项目中即可,动画开关为loadCircle和stop方法,提供了监听接口OnDoneCircleAnimListner以便于和外部逻辑衔接
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@SuppressLint("NewApi") public class LoadingCircleView extends View {
private Paint mLoadPaint;
private float mStrokeWidth = 3;
private float mCenterX, mCenterY;
private float mRadius;
private final RectF mRectF = new RectF();
private int mDegree;
private int mPaintColor = Color.RED;
private Float mOffsetValue = 0f;
private Float mOffsetRightValue = 0f;
private AnimatorSet mAnimatorSet = new AnimatorSet();
private static final float PADDING = 10;
private ValueAnimator mCircleAnim;
private ValueAnimator mLineLeftAnimator;
private ValueAnimator mLineRightAnimator;
private boolean mIsCanHide;
public LoadingCircleView(Context context) {
this(context, null);
}
public LoadingCircleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LoadingCircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mLoadPaint = new Paint();
mLoadPaint.setAntiAlias(true);
mLoadPaint.setStrokeJoin(Paint.Join.ROUND);
mLoadPaint.setStrokeWidth(mStrokeWidth);
mLoadPaint.setColor(mPaintColor);
mLoadPaint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mRectF.left = mCenterX - mRadius;
mRectF.top = mCenterY - mRadius;
mRectF.right = mCenterX + mRadius;
mRectF.bottom = mCenterY + mRadius;
canvas.drawArc(mRectF, 0, mDegree, false, mLoadPaint);
canvas.drawLine(mCenterX - mRadius / 2, mCenterY,
mCenterX - mRadius / 2 + mOffsetValue, mCenterY + mOffsetValue, mLoadPaint);
canvas.drawLine(mCenterX, mCenterY + mRadius / 2,
mCenterX + mOffsetRightValue, mCenterY + mRadius / 2 - (3f / 2f) * mOffsetRightValue, mLoadPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
lodingCircleMeasure();
}
private void lodingCircleMeasure() {
int mViewWidth = getWidth();
int mViewHeight = getHeight();
int mViewLength = Math.min(mViewHeight, mViewWidth);
mCenterX = mViewWidth / 2;
mCenterY = mViewHeight / 2;
mRadius = (mViewLength - 2 * PADDING) / 2;
}
public void loadCircle() {
if (null != mAnimatorSet && mAnimatorSet.isRunning()) {
return;
}
initDegreeAndOffset();
lodingCircleMeasure();
mCircleAnim = ValueAnimator.ofInt(0, 360);
mLineLeftAnimator = ValueAnimator.ofFloat(0, mRadius / 2f);
mLineRightAnimator = ValueAnimator.ofFloat(0, mRadius / 2f);
Log.i(TAG, "mRadius" + mRadius);
mCircleAnim.setDuration(700);
mLineLeftAnimator.setDuration(350);
mLineRightAnimator.setDuration(350);
mCircleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mDegree = (Integer) animation.getAnimatedValue();
invalidate();
}
});
mLineLeftAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mOffsetValue = (Float) valueAnimator.getAnimatedValue();
invalidate();
}
});
mLineRightAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mOffsetRightValue = (Float) animation.getAnimatedValue();
invalidate();
}
});
mAnimatorSet.play(mCircleAnim).before(mLineLeftAnimator);
mAnimatorSet.play(mLineRightAnimator).after(mLineLeftAnimator);
mAnimatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
stop();
postDelayed(new Runnable() {
@Override
public void run() {
if (mEndListner != null) {
mEndListner.onCircleDone();
}
}
}, 800);
}
});
mAnimatorSet.start();
}
public void stop() {
if (null != mCircleAnim) {
mCircleAnim.end();
}
if (null != mLineLeftAnimator) {
mLineLeftAnimator.end();
}
if (null != mLineRightAnimator) {
mLineRightAnimator.end();
}
clearAnimation();
}
public boolean isStarted() {
if (null != mAnimatorSet) {
return mAnimatorSet.isStarted();
}
return false;
}
public void initDegreeAndOffset() {
mDegree = 0;
mOffsetValue = 0f;
mOffsetRightValue = 0f;
}
public boolean IsCanHide() {
return mIsCanHide;
}
public void setCanHide(boolean mCanHide) {
this.mIsCanHide = mCanHide;
}
private OnDoneCircleAnimListner mEndListner;
public void addCircleAnimatorEndListner(OnDoneCircleAnimListner endListenr) {
if (null == mEndListner) {
this.mEndListner = endListenr;
}
}
public interface OnDoneCircleAnimListner {
void onCircleDone();
}
public void removeCircleAnimatorEndListner() {
mEndListner = null;
}
}
直接将view拷贝进项目中即可,动画开关为loadCircle和stop方法,提供了监听接口OnDoneCircleAnimListner以便于和外部逻辑衔接
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@SuppressLint("NewApi") public class LoadingCircleView extends View {
private Paint mLoadPaint;
private float mStrokeWidth = 3;
private float mCenterX, mCenterY;
private float mRadius;
private final RectF mRectF = new RectF();
private int mDegree;
private int mPaintColor = Color.RED;
private Float mOffsetValue = 0f;
private Float mOffsetRightValue = 0f;
private AnimatorSet mAnimatorSet = new AnimatorSet();
private static final float PADDING = 10;
private ValueAnimator mCircleAnim;
private ValueAnimator mLineLeftAnimator;
private ValueAnimator mLineRightAnimator;
private boolean mIsCanHide;
public LoadingCircleView(Context context) {
this(context, null);
}
public LoadingCircleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LoadingCircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mLoadPaint = new Paint();
mLoadPaint.setAntiAlias(true);
mLoadPaint.setStrokeJoin(Paint.Join.ROUND);
mLoadPaint.setStrokeWidth(mStrokeWidth);
mLoadPaint.setColor(mPaintColor);
mLoadPaint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mRectF.left = mCenterX - mRadius;
mRectF.top = mCenterY - mRadius;
mRectF.right = mCenterX + mRadius;
mRectF.bottom = mCenterY + mRadius;
canvas.drawArc(mRectF, 0, mDegree, false, mLoadPaint);
canvas.drawLine(mCenterX - mRadius / 2, mCenterY,
mCenterX - mRadius / 2 + mOffsetValue, mCenterY + mOffsetValue, mLoadPaint);
canvas.drawLine(mCenterX, mCenterY + mRadius / 2,
mCenterX + mOffsetRightValue, mCenterY + mRadius / 2 - (3f / 2f) * mOffsetRightValue, mLoadPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
lodingCircleMeasure();
}
private void lodingCircleMeasure() {
int mViewWidth = getWidth();
int mViewHeight = getHeight();
int mViewLength = Math.min(mViewHeight, mViewWidth);
mCenterX = mViewWidth / 2;
mCenterY = mViewHeight / 2;
mRadius = (mViewLength - 2 * PADDING) / 2;
}
public void loadCircle() {
if (null != mAnimatorSet && mAnimatorSet.isRunning()) {
return;
}
initDegreeAndOffset();
lodingCircleMeasure();
mCircleAnim = ValueAnimator.ofInt(0, 360);
mLineLeftAnimator = ValueAnimator.ofFloat(0, mRadius / 2f);
mLineRightAnimator = ValueAnimator.ofFloat(0, mRadius / 2f);
Log.i(TAG, "mRadius" + mRadius);
mCircleAnim.setDuration(700);
mLineLeftAnimator.setDuration(350);
mLineRightAnimator.setDuration(350);
mCircleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mDegree = (Integer) animation.getAnimatedValue();
invalidate();
}
});
mLineLeftAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mOffsetValue = (Float) valueAnimator.getAnimatedValue();
invalidate();
}
});
mLineRightAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mOffsetRightValue = (Float) animation.getAnimatedValue();
invalidate();
}
});
mAnimatorSet.play(mCircleAnim).before(mLineLeftAnimator);
mAnimatorSet.play(mLineRightAnimator).after(mLineLeftAnimator);
mAnimatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
stop();
postDelayed(new Runnable() {
@Override
public void run() {
if (mEndListner != null) {
mEndListner.onCircleDone();
}
}
}, 800);
}
});
mAnimatorSet.start();
}
public void stop() {
if (null != mCircleAnim) {
mCircleAnim.end();
}
if (null != mLineLeftAnimator) {
mLineLeftAnimator.end();
}
if (null != mLineRightAnimator) {
mLineRightAnimator.end();
}
clearAnimation();
}
public boolean isStarted() {
if (null != mAnimatorSet) {
return mAnimatorSet.isStarted();
}
return false;
}
public void initDegreeAndOffset() {
mDegree = 0;
mOffsetValue = 0f;
mOffsetRightValue = 0f;
}
public boolean IsCanHide() {
return mIsCanHide;
}
public void setCanHide(boolean mCanHide) {
this.mIsCanHide = mCanHide;
}
private OnDoneCircleAnimListner mEndListner;
public void addCircleAnimatorEndListner(OnDoneCircleAnimListner endListenr) {
if (null == mEndListner) {
this.mEndListner = endListenr;
}
}
public interface OnDoneCircleAnimListner {
void onCircleDone();
}
public void removeCircleAnimatorEndListner() {
mEndListner = null;
}
}
相关文章推荐
- mysql 多表 查询
- [置顶] 网络爬虫:利用Selenium实现登录
- [?*]Letter Combinations of a Phone Number
- Android实现微信录制小视频的计时动画
- 我是这样看搜狗搜索与知乎合作的
- OC中的protocol
- 我的个人知识管理工具一览及相关经验技巧
- 技能的十一个级别
- 一步步教你Hadoop多节点集群安装配置
- 《你必须知道的495个C语言问题》知识笔记及补充
- Python篇----正则表达式语法(基础)
- mysql约束
- 三、jQuery事件处理
- 出发吧
- FileInputStream FileOutputStream
- 信号驱动式I/O模型,以终端I/O为例写个demo
- 操作系统进程调度之多级反馈队列算法模拟实现
- MySQL重要但容易被忽略_MySQL自定义函数&存储过程
- CSS图片选择
- 20151116小问题