转载请标明出处:http://blog.csdn.net/u013598111/article/details/50073869,本文出自:【JunTao_sun】
效果图:
天好冷,好想吃面包,好想钻被窝玩手机,不多说,上代码,关键的都注释了。
可以继续改善和优化-----
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();
}
}
});
}
}