ValueAnimator實現酷炫的動畫
這篇文章主要實現用ValueAnimator實現自定義控件的一個動畫效果
先大概說一下ValueAnimator的使用ValueAnimator valueAnimator=ValueAnimator.ofFloat(0, 100f);這樣就生成了一個ValueAnimator類,ValueAnimator.ofFloat()也可以是ValueAnimator.ofInt();然后就是setDuration()設置動畫持續時間;setInterpolator(new AccelerateDecelerateInterpolator())設置攔截器(api給出了幾種效果,使用很方便的);再添加一個更新的監聽就可以開始搞事了addUpdateListener();接下來給大家看看我之前在項目中用過的一個比較復雜的動畫,代碼太長,就直接粘代碼吧,很簡單的,希望有大神能對代碼做一下改進!
public class RatingViw extends View {
//旋轉動畫,百分比動畫,評估中的動畫,評分動畫,結果動畫
private ValueAnimator rotateAnimation, perAnimation, detailAnimation, ratingAnimation, resultAnimation;
private float rotateAngle;
private List<RatingBar> RatingBars;
private int x, y; //圓心的坐標
private static final int STROKE_OFFSET = 5;
//扇形的間隙 private int currStarNum = -1; //當前星的數量
private int lastStatNum = -1; //上一顆星的數量
private int currPer; //當前的百分數
private int radius; //半徑
private int ditalAlpha, resultAlpha; //
private int maxRate = 18;
private boolean isShow; //顯示RatingView
private boolean isShowDetail = true; //顯示診斷過程
//股票名稱,百分比,百分號,結果,評估中
private Paint paint, perPaint, mPaint, resulPaint, sPaint;
private Rect rect, rect1, textRect, ditalRect, resultRect;
private String name = "", result = "80分";
private float eventX;
private float eventY;
private boolean isEmpty = false;
private String assess="評估中"; //評估中
private boolean drawResult;
private boolean isAnimationYEnd=false;
public RatingViw(Context context) {
this(context, null);
}
public RatingViw(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RatingViw(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
RatingBars = new ArrayList<>();
RatingBars.add(0, new RatingBar(0));
RatingBars.add(0, new RatingBar(0));
RatingBars.add(0, new RatingBar(0));
initAnimation();
initTextAnimation();
}
public void setName(String name) {
this.name = name;
}
public String getName(){
return name;
}
public void setResult(String result){
this.result=result+"分";
}
private void initTextAnimation() {
detailAnimation = ValueAnimator.ofInt(0, 255);
detailAnimation.setDuration(500);
detailAnimation.setInterpolator(new LinearInterpolator());
detailAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
ditalAlpha = (int) valueAnimator.getAnimatedValue();
}
});
resultAnimation = ValueAnimator.ofInt(0, 255);
resultAnimation.setDuration(500);
resultAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
resultAlpha = (int) valueAnimator.getAnimatedValue();
}
});
}
private void initAnimation() {
rotateAnimation = ValueAnimator.ofFloat(0, 360 * 5);
rotateAnimation.setDuration(3000);
rotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
rotateAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
rotateAngle = (float) valueAnimator.getAnimatedValue();
long currentPlayTime = valueAnimator.getCurrentPlayTime();
invalidate();
if (currentPlayTime > 2500) {
if (isShow) {
ratingAnimation.start();
}
}
}
});
//中間的文字
perAnimation = ValueAnimator.ofInt(0, 180);
perAnimation.setDuration(3000);
perAnimation.setInterpolator(new LinearInterpolator());
perAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
currPer = (int) valueAnimator.getAnimatedValue();
if (currPer == 50) {
detailAnimation.start();
}
if (currPer == 100) {
detailAnimation.start();
}
}
});
ratingAnimation = ValueAnimator.ofInt(0, maxRate); //18顆星
ratingAnimation.setDuration(1000);
ratingAnimation.setInterpolator(new LinearInterpolator());
ratingAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
currStarNum = (int) valueAnimator.getAnimatedValue();
//關閉百分比和詳情
isShowDetail = false;
if (currStarNum == 1) {
resultAnimation.start();
drawResult = true;
}
if (currStarNum != lastStatNum) {
invalidate();
}
lastStatNum = currStarNum;
}
});
ratingAnimation.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if (!drawResult) {
resultAnimation.start();
}
if (translation!=null)
translation.start();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
private int translationX;//評分向左移動
private int textX,textY;
private int width,height;
private int reSetX;
private ValueAnimator translation,textAnimationX,textAnimatorY,reSetAnimation; //評分左移,文字左移,
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(),getMeasuredWidth()*16/45);
}
@Override
protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
x = w / 2;
y = h / 2;
radius = y*11/16;
translation= ValueAnimator.ofInt(x,radius+h/4);
translation.setDuration(500);
translation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
translationX= (int) animation.getAnimatedValue();
x=translationX;
initRatingBar();
invalidate();
if (translationX<300){
textAnimationX.start();
textAnimatorY.start();
}
}
});
width = getMeasuredWidth();
height = getMeasuredHeight();
int d = width - 2 * radius - dip2px(getContext(), 15);
textAnimationX= ValueAnimator.ofInt(0,w*7/90,w*7/90-30,w*7/90,w*7/90-20,w*7/90,w*7/90-10,w*7/90);
textAnimationX.setDuration(500);
textAnimationX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
textX= (int) animation.getAnimatedValue();
if (textX*5>225){
textRectPaint.setAlpha(255);
textPaint.setAlpha(255);
} else {
textRectPaint.setAlpha(textX*5);
textPaint.setAlpha(textX*5);
}
initPath();
invalidate();
}
});
textAnimatorY= ValueAnimator.ofInt(0,h*3/16,h*3/16-30,h*3/16,h*3/16-20,h*3/16,h*3/16-10,h*3/16);
textAnimatorY.setDuration(500);
textAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
textY= (int) animation.getAnimatedValue();
initPath();
invalidate();
}
});
textAnimatorY.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
isAnimationYEnd=true;
if (onAnimatorListener!=null){
onAnimatorListener.onEnd();
}
}
});
reSetAnimation= ValueAnimator.ofInt(radius+h/4,width/2);
reSetAnimation.setDuration(500);
reSetAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
x= (int) animation.getAnimatedValue();
int alpha = width / 2 - x;
if (alpha>=255){
alpha=255;
}
textRectPaint.setAlpha(alpha);
textPaint.setAlpha(alpha);
initPath();
initRatingBar();
invalidate();
}
});
reSetAnimation.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
Toast.makeText(getContext(), "完成", Toast.LENGTH_SHORT).show();
show();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
initText();
initRatingBar();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isEmpty) {
canvas.save();
canvas.rotate(rotateAngle, x, y);
for (RatingBar RatingBar : RatingBars) {
RatingBar.drawUnRate(canvas);
}
canvas.restore();
canvas.save();
canvas.rotate(-rotateAngle, x, y);
for (RatingBar RatingBar : RatingBars) {
RatingBar.drawLine(canvas);
}
canvas.restore();
paint.setTextSize(radius / 5);
canvas.drawText(name, x - textRect.width() / 2, y - radius / 2, paint);
}
drawResult(canvas);
drawTranslationX(canvas);
drawText(canvas);
}
private String suggest=""; //增持
private String ranking=""; //打敗96%的股票
private String totalAccuracy=""; //89%
private String changeAccuracy=""; //較昨日提升2%
public void setSuggest(int suggest) {
String[] array = getContext().getResources().getStringArray(R.array.diagnoseRating);
if (suggest>=array.length)return;
this.suggest=array[suggest];
}
public void setRanking(String ranking) {
this.ranking = "打敗"+DigitalUtil.getNumberToNumver_towInt(ranking)+"%的股票";
}
public void setTotalAccuracy(String totalAccuracy) {
this.totalAccuracy = DigitalUtil.getNumberToNumver_towInt(totalAccuracy)+"%";
}
public void setChangeAccuracy(String changeAccuracy) {
if (TextUtils.isEmpty(changeAccuracy))return;
if (!changeAccuracy.contains("-")){
this.changeAccuracy = "較昨日提升"+DigitalUtil.getNumberToNumver_towInt(changeAccuracy)+"%";
}else {
String replace = changeAccuracy.replace("-", "");
this.changeAccuracy = "較昨日降低"+DigitalUtil.getNumberToNumver_towInt(replace)+"%";
}
}
/** * 畫最后的文字 */
private void drawText(Canvas canvas) {
textPaint.setTextSize(textY*2/5);
textPaint.getTextBounds("今日評級",0,"今日評級".length(),textRectF);
canvas.drawText("今日評級",width*235/450-textRectF.width()/2,y-height/8,textPaint);
textPaint.setTextSize(textY*2/3);
textPaint.getTextBounds(suggest,0,suggest.length(),textRectF);
canvas.drawText(suggest,width*235/450-textRectF.width()/2,y+textRectF.height()/2,textPaint);
textPaint.setTextSize(textY*2/5);
textPaint.getTextBounds(ranking,0,ranking.length(),textRectF);
canvas.drawText(ranking,width*235/450-textRectF.width()/2,y+height*3/16,textPaint);
textPaint.setTextSize(textY*2/5);
textPaint.getTextBounds("診股準確率",0,"診股準確率".length(),textRectF);
canvas.drawText("診股準確率",width*365/450-textRectF.width()/2,y-height/8,textPaint);
textPaint.setTextSize(textY*2/3);
textPaint.getTextBounds(totalAccuracy,0,totalAccuracy.length(),textRectF);
canvas.drawText(totalAccuracy,width*365/450-textRectF.width()/2,y+textRectF.height()/2,textPaint);
textPaint.setTextSize(textY*2/5);
textPaint.getTextBounds(changeAccuracy,0,changeAccuracy.length(),textRectF);
canvas.drawText(changeAccuracy,width*365/450-textRectF.width()/2,y+height*3/16,textPaint);
textPaint.getTextBounds("查看詳情>",0,"查看詳情>".length(),textRectF);
canvas.drawText("查看詳情>",width*440/450-textRectF.width(),height*15/16,textPaint);
}
private Rect textRectF;
private Paint textRectPaint,textPaint;
private Path pathA,pathB,pathC,pathD,pathAr,pathBr,pathCr,pathDr;
private void initText(){
textRectPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
textRectPaint.setColor(Color.WHITE);
textRectPaint.setAlpha(0);
textRectPaint.setStyle(Paint.Style.STROKE);
textRectPaint.setStrokeWidth(dip2px(getContext(),1));
textPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(Color.WHITE);
textPaint.setTextSize(30);
textRectF=new Rect();
textPaint.getTextBounds("今日評級",0,"今日評級".length(),textRectF);
pathA=new Path();
pathB=new Path();
pathC=new Path();
pathD=new Path();
pathAr=new Path();
pathBr=new Path();
pathCr=new Path();
pathDr=new Path();
initPath();
}
private void initPath() {
int line=width/45;
pathA.reset();
pathA.moveTo(width*225/450-textX,y-textY);
pathA.lineTo(width*225/450-textX,y-line-textY);
pathA.lineTo(width*225/450-textX+line,y-line-textY);
pathB.reset();
pathB.moveTo(width*225/450+textX+2*width/45,y-textY);
pathB.lineTo(width*225/450+textX+2*line,y-line-textY);
pathB.lineTo(width*225/450+textX+line,y-line-textY);
pathC.reset();
pathC.moveTo(width*225/450+textX+2*line,y+textY);
pathC.lineTo(width*225/450+textX+2*line,y+line+textY);
pathC.lineTo(width*225/450+textX+line,y+line+textY);
pathD.reset();
pathD.moveTo(width*225/450-textX,y+textY);
pathD.lineTo(width*225/450-textX,y+line+textY);
pathD.lineTo(width*225/450-textX+line,y+line+textY);
pathAr.reset();
pathAr.moveTo(width*355/450-textX,y-textY);
pathAr.lineTo(width*355/450-textX,y-line-textY);
pathAr.lineTo(width*355/450+line-textX,y-line-textY);
pathBr.reset();
pathBr.moveTo(width*355/450+2*line+textX,y-textY);
pathBr.lineTo(width*355/450+2*line+textX,y-line-textY);
pathBr.lineTo(width*355/450+line+textX,y-line-textY);
pathCr.reset();
pathCr.moveTo(width*355/450+2*line+textX,y+textY);
pathCr.lineTo(width*355/450+2*line+textX,y+line+textY);
pathCr.lineTo(width*355/450+line+textX,y+line+textY);
pathDr.reset();
pathDr.moveTo(width*355/450-textX,y+textY);
pathDr.lineTo(width*355/450-textX,y+line+textY);
pathDr.lineTo(width*355/450+line-textX,y+line+textY);
}
/**
* 畫平移動畫
* @param canvas 畫布
*/
private void drawTranslationX(Canvas canvas) {
if (translationX>0){
canvas.drawPath(pathA,textRectPaint);
canvas.drawPath(pathB,textRectPaint);
canvas.drawPath(pathC,textRectPaint);
canvas.drawPath(pathD,textRectPaint);
canvas.drawPath(pathAr,textRectPaint);
canvas.drawPath(pathBr,textRectPaint);
canvas.drawPath(pathCr,textRectPaint);
canvas.drawPath(pathDr,textRectPaint);
}
}
private static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
public static int getScreenWidth(Context context) {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}
private void drawResult(Canvas canvas) {
if (isShow) {
//畫沒有評分的所有的item
canvas.save();
canvas.rotate(rotateAngle, x, y);
for (RatingBar RatingBar : RatingBars) {
RatingBar.drawUnRate(canvas);
}
canvas.restore();
canvas.save();
canvas.rotate(-rotateAngle, x, y);
for (RatingBar RatingBar : RatingBars) {
RatingBar.drawLine(canvas);
}
canvas.restore();
canvas.drawText(name, x - textRect.width() / 2, y - radius / 5, paint);
if (isShowDetail){
drawPer(canvas);
}
//畫星
if (currStarNum != -1) {
for (RatingBar RatingBar : RatingBars) {
for (int i = 0; i < RatingBar.getCurrRate(); i++) {
if (i <= currStarNum) {
//每次都要講之前的畫出來,不然之前的就沒有了
RatingBar.drawRating(canvas, i);
}
}
}
}
//畫結果
if (resultAlpha > 0) {
resulPaint.setAlpha(resultAlpha);
canvas.drawText(result, x - resultRect.width() / 2, y + radius / 5*2, resulPaint);
}
}
}
private void drawPer(Canvas canvas) {
canvas.drawText("%", x + 2 * rect.width() / 3, y + radius / 3, mPaint);
if (0<currPer&&currPer <= 30) {
canvas.drawText("" + currPer, x - rect.width() / 2, y + radius / 3, perPaint);
if (ditalAlpha > 0) {
canvas.drawText(assess, x - ditalRect.width() / 2, y + radius / 3 + ditalRect.height()*3/2, sPaint);
}
}
if (currPer > 30 && currPer < 50) {
canvas.drawText("" + 30, x - rect.width() / 2, y + radius / 3, perPaint);
if (ditalAlpha > 0) {
canvas.drawText(assess, x - ditalRect.width() / 2, y + radius / 3 + ditalRect.height()*3/2, sPaint);
}
}
if (currPer >= 50 && currPer <= 80) {
canvas.drawText("" + (currPer - 20), x - rect.width() / 2, y + radius / 3, perPaint);
if (ditalAlpha > 0) {
canvas.drawText(assess, x - ditalRect.width() / 2, y + radius / 3 + ditalRect.height()*3/2, sPaint);
}
}
if (currPer > 80 && currPer < 100) {
canvas.drawText("" + 60, x - rect.width() / 2, y + radius / 3, perPaint);
if (ditalAlpha > 0) {
canvas.drawText(assess, x - ditalRect.width() / 2, y + radius / 3 + ditalRect.height()*3/2, sPaint);
}
}
if (currPer >= 100 && currPer <= 130) {
canvas.drawText("" + (currPer - 40), x - rect.width() / 2, y + radius / 3, perPaint);
if (ditalAlpha > 0) {
canvas.drawText(assess, x - ditalRect.width() / 2, y + radius / 3 + ditalRect.height()*3/2, sPaint);
}
}
if (currPer > 130 && currPer < 150) {
canvas.drawText("" + 90, x - rect.width() / 2, y + radius / 3, perPaint);
if (ditalAlpha > 0) {
canvas.drawText(assess, x - ditalRect.width() / 2, y + radius / 3 + ditalRect.height()*3/2, sPaint);
}
}
if (currPer >= 150 && currPer < 160) {
canvas.drawText("" + (currPer - 60), x - 2 * rect.width() / 3, y + radius / 3, perPaint);
}
if (currPer >= 160) {
canvas.drawText("" + 100, x - 2 * rect1.width() / 3, y + radius / 3, perPaint);
}
}
private void initRatingBar() {
int dividePart = RatingBars.size();
if (dividePart == 0) {
return;
}
int sweepAngle = dividePart == 1 ? 360 : (360 - dividePart * STROKE_OFFSET) / dividePart;
int rotateOffset = dividePart == 1 ? 90 : 90 + sweepAngle / 2 - 3;
for (int i = 0; i < dividePart; i++) {
float startAngle = i * (sweepAngle + STROKE_OFFSET) - rotateOffset;
RatingBar RatingBar = RatingBars.get(i);
if (dividePart == 1) {
RatingBar.setSingle(true);
}
RatingBar.setX(x);
RatingBar.setY(y);
RatingBar.setStartAngle(startAngle);
RatingBar.setSweepAngle(sweepAngle);
RatingBar.init(maxRate);
radius = RatingBar.getRadius();
}
initPaint();
}
private void initPaint() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(radius / 4);
paint.setColor(Color.WHITE);
paint.setAlpha((int) (255 * 0.6));
perPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
perPaint.setAlpha(255);
perPaint.setTextSize(radius / 2);
perPaint.setColor(Color.WHITE);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setTextSize(radius / 4);
mPaint.setColor(Color.WHITE);
mPaint.setAlpha(255);
resulPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
resulPaint.setAlpha((int) (255 * 0.7));
resulPaint.setColor(Color.WHITE);
resulPaint.setTextSize(radius / 2);
sPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
sPaint.setAlpha((int) (255 * 0.6));
sPaint.setColor(Color.WHITE);
sPaint.setTextSize(radius / 6);
rect = new Rect();
perPaint.getTextBounds("10", 0, "10".length(), rect);
rect1 = new Rect();
perPaint.getTextBounds("100", 0, "100".length(), rect1);
textRect = new Rect();
paint.getTextBounds(name, 0, name.length(), textRect);
ditalRect = new Rect();
sPaint.getTextBounds(assess,0,assess.length(),ditalRect);
resultRect = new Rect();
resulPaint.getTextBounds(result, 0, result.length(), resultRect);
}
public void addRatingBar(RatingBar RatingBar) {
RatingBar.add(RatingBar);
}
public void show() {
if (RatingBar.size() == 0) {
return;
}
isShow = true;
isEmpty = false;
if (rotateAnimation != null) {
rotateAnimation.cancel();
}
initRatingBar();
rotateAnimation.setRepeatCount(0); //旋轉動畫
rotateAnimation.start(); //百分比動畫
perAnimation.start(); //評估中動畫
detailAnimation.start();
if (onAnimatorListener!=null){
onAnimatorListener.onStart();
}
}
public void showEmpty() {
isEmpty = true;
initEmpty();
invalidate();
rotateAnimation.setRepeatMode(ValueAnimator.RESTART);
rotateAnimation.setRepeatCount(ValueAnimator.INFINITE);
rotateAnimation.start();
}
private void initEmpty() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(radius / 5); //
paint.setColor(Color.WHITE);
paint.setAlpha((int) (255 * 0.6));
textRect = new Rect();
paint.getTextBounds(name, 0, name.length(), textRect);
}
public void clear() {
rotateAnimation.end();
rotateAnimation.cancel();
RatingBar.clear();
isShow = false;
ditalAlpha=0;
resultAlpha=0;
currStarNum=-1;
isShowDetail=true;
invalidate();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
eventX = event.getX();
eventY = event.getY();
break;
case MotionEvent.ACTION_UP:
float resX = Math.abs(event.getX() - eventX);
float resY = Math.abs(event.getY() - eventY);
if (resX<10&&resY<10){
if (isAnimationYEnd){
Log.e("HHH", "onTouchEvent: " + event.getX() +"---"+ event.getY() +"---"+ width*365/450 +"---"+ height*15/16 );
if (event.getX()>=width-textRectF.width()*3/2 && event.getX()<width && event.getY()>=height-2*textRectF.height() && event.getY()<height) {
if (onClickRatingViewListener!=null){
onClickRatingViewListener.onClick();
}
}
}
}
break;
}
return true;
}
public void reSet(){
name="";
ditalAlpha=0;
resultAlpha=0;
currStarNum=-1;
reSetAnimation.start();
}
private OnClickRatingViewListener onClickRatingViewListener;
public void setOnClickRatingViewListener(OnClickRatingViewListener onClickRatingViewListener) {
this.onClickRatingViewListener = onClickRatingViewListener;
}
public interface OnClickRatingViewListener{
void onClick();
}
private OnAnimatorListener onAnimatorListener;
public void setOnAnimatorListener(OnAnimatorListener onAnimatorListener) {
this.onAnimatorListener = onAnimatorListener;
}
public interface OnAnimatorListener{
void onStart();
void onEnd();
}
}
啊啊啊!!!一行一行的格式化代碼好麻煩啊,有沒有大神知道快速格式化代碼的嗎
下面是每個小格
public class RatingBar {
private static final int ITEM_OFFSET = 1; //每個小item的間隙
private static final int UN_RATING_ALPHA = (int) (255 * 0.3); //沒被選中的item的透明度
private static final int OUTLINE_ALPHA = (int) (255 * 0.4); //外面的線的透明度
private static final int RATING_ALPHA = (int) (255 * 0.8); //評分的透明度
private int ratingAlpha;
private float startAngle; //每扇形開始的角度
private int sweepAngle; //每個扇形的角度
private int ratingBarWidth; //評分的寬度
private int outLineWidth; //外面的線的寬度
private int maxRate = 18; //總分數
private int currRate; //當前的評分數
private int radius; //半徑
private int x, y; //位置
private List<Rate> rates;
private Paint paint, outLinrPaint, ratingPaint;
private RectF rectF, outLineRectF;
private boolean isSingle = false;
public RatingBar(int currRate) {
this.currRate = currRate;
ratingAlpha=RATING_ALPHA;
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
outLinrPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
outLinrPaint.setColor(Color.WHITE);
ratingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
ratingPaint.setColor(Color.WHITE);
}
void init(int maxRate) {
this.maxRate=maxRate;
initRaingBar();
initRectF();
initPaint();
}
private void initPaint() {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(ratingBarWidth);
paint.setAlpha(UN_RATING_ALPHA);
outLinrPaint.setStyle(Paint.Style.STROKE);
outLinrPaint.setStrokeWidth(outLineWidth);
outLinrPaint.setAlpha(OUTLINE_ALPHA);
ratingPaint.setStyle(Paint.Style.STROKE);
ratingPaint.setStrokeWidth(ratingBarWidth);
ratingPaint.setAlpha(ratingAlpha);
}
private void initRectF() {
radius = y / 4*3;
ratingBarWidth = radius / 8;
outLineWidth = ratingBarWidth / 4;
int outLineRadius = radius -outLineWidth/2;
int ratingBarRadius = radius - ratingBarWidth / 2-5*outLineWidth;
rectF = new RectF();
rectF.left = x - ratingBarRadius;
rectF.top = y - ratingBarRadius;
rectF.right = x + ratingBarRadius;
rectF.bottom = y + ratingBarRadius;
outLineRectF = new RectF();
outLineRectF.left = x - outLineRadius;
outLineRectF.top = y - outLineRadius;
outLineRectF.right = x + outLineRadius;
outLineRectF.bottom = y + outLineRadius;
}
private void initRaingBar() {
rates = new ArrayList<>();
float itemSweepAngle;
if (isSingle) {
itemSweepAngle = (sweepAngle - (ITEM_OFFSET * maxRate)) / maxRate;
} else {
//計算每個item的弧度
itemSweepAngle = (sweepAngle - (ITEM_OFFSET * (maxRate - 1))) / maxRate;
}
for (int i = 0; i < maxRate; i++) {
//計算每個item的開始角度
float itemstartAngle = startAngle + i * (itemSweepAngle + ITEM_OFFSET);
rates.add(new Rate(itemstartAngle, itemSweepAngle));
}
}
void drawUnRate(Canvas canvas) {
for (Rate rate : rates) {
rate.drawArc(canvas, rectF, paint);
}
}
void drawLine(Canvas canvas) {
//周長
canvas.drawArc(outLineRectF, startAngle-3, sweepAngle, false, outLinrPaint);
}
void drawRating(Canvas canvas, int index) {
if (index > currRate) {
return;
}
Rate rate = rates.get(index);
rate.drawRate(canvas, rectF, ratingPaint);
}
void setStartAngle(float startAngle) {
this.startAngle = startAngle;
}
void setSweepAngle(int sweepAngle) {
this.sweepAngle = sweepAngle;
}
void setX(int x) {
this.x = x;
}
void setY(int y) {
this.y = y;
}
void setSingle(boolean single) {
isSingle = single;
}
int getRadius() {
return radius;
}
int getCurrRate() {
return currRate;
}
private class Rate {
private float startAngle, sweepAngle; //每個小格的角度
Rate(float startAngle, float sweepAngle) {
this.startAngle = startAngle;
this.sweepAngle = sweepAngle;
}
void drawArc(Canvas canvas, RectF oval, Paint paint) {
canvas.drawArc(oval, startAngle, sweepAngle, false, paint);
}
void drawRate(Canvas canvas, RectF rectF, Paint paint) {
canvas.drawArc(rectF, startAngle, sweepAngle, false, paint);
}
}
}
代碼看著很多,但是原理很簡單,邏輯有點亂,可以說ValueAnimator的作用就是用來計時的,但是在以前有個項目中用ValueAnimator來做循環倒計時,大概代碼如下:
animator=ValueAnimator.ofInt(5,0);
animator.setDuration(5000);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
time=(int)valueAnimator.getAnimatedValue();
text.setText(String.valueOf(time));
}});
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
animator.start(); //當動畫結束后又繼續該動畫,實現一個無限循環的效果
}});
就用動畫實現一個無限循環的效果,想像的很美好,但是一運行這個動畫只執行了兩次,第二次結束后就沒有繼續了,苦思冥想,各種測試最后找到一個方法,就是在結束的時候用handler來發送一個消息,在接收消息那里再啟動動畫,這個動畫就可以實現無線循環了,具體原因為什么呢?有沒有大神知道的給我留個言吧。
在運行這個評分動畫的時候也發現了一個問題,在動畫更新的監聽中long currentPlayTime = valueAnimator.getCurrentPlayTime();這個方法在大部分手機沒有問題,但就在華為榮耀8的7.0的手機上出現了動畫不按套路出牌的效果,根據動畫的效果來看發現問題出在這里,由于這里有個啟動動畫,這個動畫就在這里亂套了,然而打印出currentPlayTime ,奇怪的是在第一次運行的時候沒有任何異常,在第二次的時候currentPlayTime 的初始值不是0,而是當前動畫從開始執行到現在的總共時間,用其他手機來測試,沒有發現異常,再看源碼里面也沒有關于版本的代碼,就暫時在currentPlayTime 這里判斷了一下,如果大于總時間就等于0,然后再來榮耀上運行,歐拉,暫時沒有問題了。
最后附上截圖-O(∩_∩)O哈哈~
GIF.gif
來自:http://www.jianshu.com/p/b8d3e833d3c9