Android自定义View动画(进度条)


转载请标明出处:http://blog.csdn.net/u013598111/article/details/50073869,本文出自:【JunTao_sun】


效果图:

Android自定义View动画(进度条)_第1张图片

天好冷,好想吃面包,好想钻被窝玩手机,不多说,上代码,关键的都注释了。 

可以继续改善和优化-----


package com.example.circle;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;

public class MyView extends View {
	// 灰色画笔
	private Paint mGrayPaint;
	// 画圆笔
	private Paint mCirclePaint;
	// 文字画笔
	private Paint mTextPaint;

	private int padding = 10;
	// 半径
	private int radius = 25;
	// 控件宽度
	private int width;
	// 控件高度
	private int height;
	// 默认3个圆
	private int numberCircle = 3;
	// 减去padding的实际宽度
	private int realWidth;
	// 每一行的宽度
	private int eachLineWidth;
	// 连接线的数目
	private int lineSum = numberCircle - 1;
	private String firstTitle = "每日一句";
	private String secondTitle = "阳光灿烂";
	private String lastTitle = "橘子群岛";
	private Rect mRect = new Rect();
	// 文字的距离控件中心的距离
	private int topPadding = 40;
	private float changeValue = 0;
	private boolean isFirst = true;
	private int paintStyleRadius = 5;
	private Paint mCircle;

	public MyView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mCirclePaint.setDither(true);
		mCirclePaint.setColor(Color.parseColor("#FF6600"));
		mCirclePaint.setStyle(Paint.Style.STROKE);
		mCirclePaint.setStrokeCap(Paint.Cap.ROUND);
		mCirclePaint.setStyle(Paint.Style.FILL);

		mCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
		mCircle.setDither(true);
		mCircle.setColor(Color.parseColor("#FF6600"));
		mCircle.setStyle(Paint.Style.STROKE);
		mCircle.setStrokeCap(Paint.Cap.ROUND);
		mCircle.setStrokeWidth(2);

		mGrayPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mGrayPaint.setDither(true);
		mGrayPaint.setStyle(Paint.Style.FILL_AND_STROKE);
		mGrayPaint.setStrokeWidth(5);
		mGrayPaint.setColor(0xaaa1afc9);
		mGrayPaint.setStrokeCap(Paint.Cap.ROUND);
		// 设置绘制时各图形的结合方式,如平滑效果等
		mGrayPaint.setStrokeJoin(Paint.Join.ROUND);
		mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mTextPaint.setDither(true);
		mTextPaint.setColor(Color.parseColor("#0066FF"));

		initAniamtionPaint();

	}

	private Paint mPaintAnimaL;

	private void initAniamtionPaint() {
		mPaintAnimaL = new Paint(Paint.ANTI_ALIAS_FLAG);
		mPaintAnimaL.setDither(true);
		mPaintAnimaL.setColor(Color.parseColor("#33FF33"));
		mPaintAnimaL.setStrokeWidth(5);
		mPaintAnimaL.setStrokeCap(Paint.Cap.ROUND);

	}

	public MyView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);

	}

	public MyView(Context context) {
		this(context, null);

	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		textMeasure();
	}

	private void textMeasure() {
		mTextPaint.getTextBounds(firstTitle, 0, firstTitle.length(), mRect);

	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		// TODO Auto-generated method stub
		super.onSizeChanged(w, h, oldw, oldh);
		this.width = w;
		this.height = h;
		realWidth = w - 2 * padding;
		// 线 得到最大的宽度
		eachLineWidth = (realWidth - 6 * radius) / (numberCircle - 1);
	}

	@Override
	protected void onDraw(Canvas canvas) {

		super.onDraw(canvas);
		// 第一条线的起始 也就是left 2.5是笔刷的半径 不然会越界
		int lineLeft = (int) (2 * radius + padding + 2.5);
		// 第一条线的right
		int lineRight = (int) (lineLeft + eachLineWidth);
		// 第二条线的起始 left (第一条线的末端right+圆的直径)
		int nextLineLeft = (int) (lineRight + 2 * (radius + 2.5) - 2.5);
		// 第二条线的right
		int nextLineRight = nextLineLeft + eachLineWidth;
		// 第一个圆的中心 半径加上leftpadding
		int circleCenter = (int) (radius + padding);
		// 第二个圆的下个中心点 2.5是笔刷的半径 不然会越界
		int circleNextCenter = (int) (lineRight + radius + 2.5);
		// 第三个圆的中心点 2.5是笔刷的半径 不然会越界
		int circleLastCenter = (int) (nextLineRight + radius + 2.5);
		// 统一高度 height / 2-长度(因为不能在控件的正中 底下还有文字)
		int unifyHeight = height / 2 - radius;
		// 第个描述文字的left (圆的中心减去文字宽度的一半)
		int firstTextLeft = circleCenter - mRect.width() / 2;
		// 统一的 文字的起始高度 文字最低高度
		int unifyHeightWithText = height / 2 + topPadding;
		// 第二个文字描述的left
		int secondTextLeft = circleNextCenter - mRect.width() / 2;
		int lastTextLeft = circleLastCenter - mRect.width() / 2;
		// 画线***********************************************************************************

		canvas.drawLine(lineLeft, unifyHeight, lineRight, unifyHeight,
				mGrayPaint);
		canvas.drawLine(nextLineLeft, unifyHeight, nextLineRight, unifyHeight,
				mGrayPaint);

		// 画圆***********************************************************************************

		canvas.drawCircle(circleCenter, unifyHeight, radius, mCircle);
		canvas.drawCircle(circleNextCenter, unifyHeight, radius, mCircle);
		canvas.drawCircle(circleLastCenter, unifyHeight, radius, mCircle);

		// 画文字***********************************************************************************

		canvas.drawText(firstTitle, firstTextLeft, unifyHeightWithText,
				mTextPaint);
		canvas.drawText(secondTitle, secondTextLeft, unifyHeightWithText,
				mTextPaint);
		canvas.drawText(lastTitle, lastTextLeft, unifyHeightWithText,
				mTextPaint);
		RectF iconRect = new RectF();
		// 圆的外矩形 圆中心 减半径
		iconRect.set(circleCenter - radius, unifyHeight - radius, circleCenter
				+ radius, unifyHeight + radius);

		Path mpath = new Path();
		mpath.addArc(iconRect, changeValue,  changeValue);

		canvas.drawPath(mpath, mCirclePaint);
		if (isFirst) {
			// 开启一次
			isFirst = false;
			// 初始化动画执行 先后类型
			type = 1;
			lineType = 1;
			// 开始动画
			verticalRun();
		}
		// 动画进度*************************************************************************************

		if (isStart) {
			// 第一条线 的进度
			float rateLineOne = lineRate1 * 1.0f / eachLineWidth
					* eachLineWidth;
			// 第二条线的进度
			float rateLineTwo = lineRate2 * 1.0f / eachLineWidth
					* eachLineWidth;
			canvas.drawLine(lineLeft, unifyHeight, lineLeft + rateLineOne,
					unifyHeight, mPaintAnimaL);

			if (C2 == 2) {// 条件满足 既第一条线完就执行

				// 第二个圆
				iconRect.set(circleNextCenter - radius, unifyHeight - radius,
						circleNextCenter + radius, unifyHeight + radius);
				// 第二个;路径
				Path mpath2 = new Path();
				mpath.addArc(iconRect, 0, changeValue2);
				canvas.drawPath(mpath, mCirclePaint);

			}

			// 画线
			if (flag2 == 2)

				canvas.drawLine(nextLineLeft, unifyHeight, nextLineLeft
						+ rateLineTwo, unifyHeight, mPaintAnimaL);
			// 第三个圆

			if (C3 == 3) {

				iconRect.set(circleLastCenter - radius, unifyHeight - radius,
						circleLastCenter + radius, unifyHeight + radius);
				// 第二个;路径
				Path mpath3 = new Path();
				mpath.addArc(iconRect, changeValue3, changeValue3);
				canvas.drawPath(mpath, mCirclePaint);
			}

		}
	}

	private float changeValue2;
	private float changeValue3;
	// changeValue的类型
	private int type;
	private int lineType;
	// 画圆的标志
	private int C2;
	private int C3;

	public void verticalRun() {
		final ValueAnimator animator = ValueAnimator.ofFloat(0, 360);
		animator.addListener(new AnimatorListener() {

			@Override
			public void onAnimationStart(Animator animation) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onAnimationRepeat(Animator animation) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onAnimationEnd(Animator animation) {
				if (C2 == 2) {
					flag2 = 2;// 第二条线的动画条件
					lineType = 2;// 画第二条线
				}

				if (C3 == 3)
					return;// 第三个圆结束动画

				isStart = true;
				lineAniamtion(eachLineWidth);
				postInvalidate();

			}

			@Override
			public void onAnimationCancel(Animator animation) {
				// TODO Auto-generated method stub

			}
		});
		animator.setDuration(2000).start();

		animator.addUpdateListener(new AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {

				if (type == 1) {
					changeValue = (Float) animation.getAnimatedValue();
					postInvalidate();
				}
				if (type == 2) {
					changeValue2 = (Float) animation.getAnimatedValue();
					postInvalidate();
				}
				if (type == 3) {
					changeValue3 = (Float) animation.getAnimatedValue();
					postInvalidate();
				}

			}
		});
	}

	private float lineRate1, lineRate2;
	private int flag, flag2;
	// 动画是否开始
	private boolean isStart = false;

	public void lineAniamtion(int l) {

		ValueAnimator animator = ValueAnimator.ofFloat(0, l);

		animator.setDuration(2000).start();
		animator.addListener(new AnimatorListener() {

			@Override
			public void onAnimationStart(Animator animation) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onAnimationRepeat(Animator animation) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onAnimationEnd(Animator animation) {

				C2 = 2;// 第一条线画完 执行第二个圆 动画
				type = 2;// 第二个圆的变量值
				// 如果当前二个条线画完 直接画第三个圆
				if (lineType == 2) {
					C3 = 3;
					type = 3;
				}

				verticalRun();
				postInvalidate();

			}

			@Override
			public void onAnimationCancel(Animator animation) {
				// TODO Auto-generated method stub

			}
		});

		animator.addUpdateListener(new AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				if (lineType == 1) {
					// 第一条线的的进度值
					lineRate1 = (Float) animation.getAnimatedValue();
					postInvalidate();
				}
				if (lineType == 2) {
					// 第二条线的的进度值
					lineRate2 = (Float) animation.getAnimatedValue();
					postInvalidate();
				}

			}
		});

	}

}









你可能感兴趣的:(android自定义控件,android提高篇)