package com.yidianling.common.view; import android.animation.Animator; import android.animation.ValueAnimator; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AccelerateInterpolator; import android.view.animation.LinearInterpolator; import android.widget.FrameLayout; import com.yidianling.common.R; import com.yidianling.common.tools.RxImageTool; import java.util.ArrayList; /** * Created by Vondear on 2017/10/9. * */ public class RxRotateBar extends FrameLayout { private static final int STROKE_OFFSET = 10; private static final long ROTATING_ANIMATION_DURATION = 3000L; private static final long RATING_ANIMATION_DURATION = 3000L; private static final long TEXT_ANIMATION_DURATION = 1000L; /** * animator callback listener */ private AnimatorListener mAnimatorListener; // style attr private int mRatedColor, mUnratedColor, mTitleColor, mOutlineColor, mDefaultColor; private boolean isShowTitle = true; private int mRatingMax; private boolean isShow = false; private int mCenterX, mCenterY; private float rotateAngle; private int ratingGap = -1, textAlpha = 0; private ArrayList<RxRotateBarBasic> mRatingBars; private ValueAnimator rotateAnimator, ratingAnimator, titleAnimator; private Paint mCenterTextPaint; private int mCenterTextColor; // 蛛网等级填充的颜色 private int mCenterTextSize = 40; private String mCenterText = ""; private boolean isShowCenterTitle = false; public RxRotateBar(Context context) { super(context); } public RxRotateBar(Context context, AttributeSet attrs) { super(context, attrs); // call onDraw in ViewGroup setWillNotDraw(false); initAttrs(context, attrs); mRatingBars = new ArrayList<>(); initRotatingAnimation(); initRatingAnimation(); initTextAnimation(); } private void initAttrs(Context context, AttributeSet attrs) { //load styled attributes. final TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.RxRotateBar, 0, 0); mCenterText = attributes.getString(R.styleable.RxRotateBar_ratingCenterTitle);//中心标题 mCenterTextSize = attributes.getDimensionPixelSize(R.styleable.RxRotateBar_centerTitleSize, RxImageTool.dip2px(20));//标题字体大小 mRatedColor = attributes.getColor(R.styleable.RxRotateBar_ratingRatedColor, 0); mUnratedColor = attributes.getColor(R.styleable.RxRotateBar_ratingUnratedColor, 0); mTitleColor = attributes.getColor(R.styleable.RxRotateBar_ratingTitleColor, 0); mOutlineColor = attributes.getColor(R.styleable.RxRotateBar_ratingOutlineColor, 0); mCenterTextColor = attributes.getColor(R.styleable.RxRotateBar_ratingCenterColor, Color.WHITE); mDefaultColor = attributes.getColor(R.styleable.RxRotateBar_ratingDefaultColor, 0); isShowTitle = attributes.getBoolean(R.styleable.RxRotateBar_ratingTitleVisible, true); mRatingMax = attributes.getInt(R.styleable.RxRotateBar_ratingMax, 0); attributes.recycle(); } private void initTextAnimation() { titleAnimator = ValueAnimator.ofInt(0, 255); titleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { textAlpha = (int) animation.getAnimatedValue(); invalidate(); } }); titleAnimator.setDuration(TEXT_ANIMATION_DURATION); titleAnimator.setInterpolator(new AccelerateInterpolator()); } public void initRotatingAnimation() { rotateAnimator = ValueAnimator.ofFloat(0.0f, 360f * 3); rotateAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { rotateAngle = (float) animation.getAnimatedValue(); invalidate(); } }); rotateAnimator.setDuration(ROTATING_ANIMATION_DURATION); rotateAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); rotateAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { if (mAnimatorListener != null) { mAnimatorListener.onRotateStart(); } } @Override public void onAnimationEnd(Animator animation) { isShowCenterTitle = true; if (mAnimatorListener != null) { mAnimatorListener.onRotateEnd(); } titleAnimator.start(); ratingAnimator.start(); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); } public void initRatingAnimation() { ratingAnimator = ValueAnimator.ofInt(0, 9); ratingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { ratingGap = (int) animation.getAnimatedValue(); invalidate(); } }); ratingAnimator.setDuration(RATING_ANIMATION_DURATION); ratingAnimator.setInterpolator(new LinearInterpolator()); rotateAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { if (mAnimatorListener != null) { mAnimatorListener.onRatingStart(); } } @Override public void onAnimationEnd(Animator animation) { isShowCenterTitle = true; if (mAnimatorListener != null) { mAnimatorListener.onRatingEnd(); } } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mCenterX = w / 2; mCenterY = h / 2; initRatingBar(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //初始化字体画笔 mCenterTextPaint = new Paint(); mCenterTextPaint.setAntiAlias(true); mCenterTextPaint.setColor(mCenterTextColor); mCenterTextPaint.setTextSize(mCenterTextSize); if (isShow) { canvas.save(); canvas.rotate(rotateAngle, mCenterX, mCenterY); for (RxRotateBarBasic ratingBar : mRatingBars) { ratingBar.drawOutLine(canvas); } canvas.restore(); canvas.save(); canvas.rotate(-rotateAngle, mCenterX, mCenterY); for (RxRotateBarBasic ratingBar : mRatingBars) { ratingBar.drawUnRate(canvas); ratingBar.drawShadow(canvas); } canvas.restore(); if (ratingGap != -1) { for (RxRotateBarBasic ratingBar : mRatingBars) { for (int rate = 0; rate < ratingBar.getRate(); rate++) { if (rate <= ratingGap) { ratingBar.drawRate(canvas, rate); } } } } for (RxRotateBarBasic ratingBar : mRatingBars) { ratingBar.drawTitle(canvas, textAlpha); } float textWidth = mCenterTextPaint.measureText(mCenterText); Paint.FontMetrics fontMetrics = mCenterTextPaint.getFontMetrics(); float textHeight = fontMetrics.descent - fontMetrics.ascent; if (isShowCenterTitle) { canvas.drawText(mCenterText, mCenterX - textWidth / 2, mCenterY + textHeight / 4, mCenterTextPaint); } } } public void addRatingBar(RxRotateBarBasic ratingBar) { mRatingBars.add(ratingBar); } public void removeRatingBar(RxRotateBarBasic ratingBar) { mRatingBars.remove(ratingBar); } public void removeAll() { mRatingBars.removeAll(mRatingBars); clear(); } public void clear() { isShow = false; ratingGap = -1; textAlpha = 0; } public void show() { isShowCenterTitle = false; titleAnimator.cancel(); ratingAnimator.cancel(); if (mRatingBars.size() == 0) { return; } initRatingBar(); rotateAnimator.start(); isShow = true; } private void initRatingBar() { int dividePart = mRatingBars.size(); int sweepAngle = dividePart == 1 ? 360 : (360 - dividePart * STROKE_OFFSET) / dividePart; int rotateOffset = dividePart == 1 ? 90 : 90 + sweepAngle / 2; for (int i = 0; i < dividePart; i++) { float startAngle = i * (sweepAngle + STROKE_OFFSET) - rotateOffset; RxRotateBarBasic ratingBar = mRatingBars.get(i); if (dividePart == 1) { // only show one rating bar ratingBar.setIsSingle(true); } ratingBar.setCenterX(mCenterX); ratingBar.setCenterY(mCenterY); ratingBar.setStartAngle(startAngle); ratingBar.setSweepAngle(sweepAngle); // style attr ratingBar.isShowTitle(isShowTitle); if (mDefaultColor != 0) { ratingBar.setRatingBarColor(mDefaultColor); } if (mTitleColor != 0) { ratingBar.setTitleColor(mTitleColor); } if (mRatedColor != 0) { ratingBar.setRatedColor(mRatedColor); } if (mUnratedColor != 0) { ratingBar.setUnRatedColor(mUnratedColor); } if (mOutlineColor != 0) { ratingBar.setOutlineColor(mOutlineColor); } if (mRatingMax != 0) { ratingBar.setMaxRate(mRatingMax); } ratingBar.init(); } } public AnimatorListener getAnimatorListener() { return mAnimatorListener; } public void setAnimatorListener(AnimatorListener mAnimatorListener) { this.mAnimatorListener = mAnimatorListener; } public void isShowTitle(boolean isShowTitle) { this.isShowTitle = isShowTitle; } public void setDefaultColor(int color) { this.mDefaultColor = color; } public int getCenterTextColor() { return mCenterTextColor; } public void setCenterTextColor(int centerTextColor) { mCenterTextColor = centerTextColor; invalidate(); } public int getCenterTextSize() { return mCenterTextSize; } public void setCenterTextSize(int centerTextSize) { mCenterTextSize = centerTextSize; invalidate(); } public String getCenterText() { return mCenterText; } public void setCenterText(String centerText) { mCenterText = centerText; invalidate(); } public interface AnimatorListener { void onRotateStart(); void onRotateEnd(); void onRatingStart(); void onRatingEnd(); } }