ValueAnimator实现酷炫的动画

bnxrrta85 3年前
   <p>这篇文章主要实现用ValueAnimator实现自定义控件的一个动画效果</p>    <p>先大概说一下ValueAnimator的使用ValueAnimator valueAnimator=ValueAnimator.ofFloat(0, 100f);这样就生成了一个ValueAnimator类,ValueAnimator.ofFloat()也可以是ValueAnimator.ofInt();然后就是setDuration()设置动画持续时间;setInterpolator(new AccelerateDecelerateInterpolator())设置拦截器(api给出了几种效果,使用很方便的);再添加一个更新的监听就可以开始搞事了addUpdateListener();接下来给大家看看我之前在项目中用过的一个比较复杂的动画,代码太长,就直接粘代码吧,很简单的,希望有大神能对代码做一下改进!</p>    <pre>  <code class="language-java">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();      }  }</code></pre>    <h2>啊啊啊!!!一行一行的格式化代码好麻烦啊,有没有大神知道快速格式化代码的吗</h2>    <p>下面是每个小格</p>    <pre>  <code class="language-java">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);          }      }  }</code></pre>    <p>代码看着很多,但是原理很简单,逻辑有点乱,可以说ValueAnimator的作用就是用来计时的,但是在以前有个项目中用ValueAnimator来做循环倒计时,大概代码如下:</p>    <pre>  <code class="language-java">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();  //当动画结束后又继续该动画,实现一个无限循环的效果      }});</code></pre>    <p>就用动画实现一个无限循环的效果,想像的很美好,但是一运行这个动画只执行了两次,第二次结束后就没有继续了,苦思冥想,各种测试最后找到一个方法,就是在结束的时候用handler来发送一个消息,在接收消息那里再启动动画,这个动画就可以实现无线循环了,具体原因为什么呢?有没有大神知道的给我留个言吧。</p>    <p>在运行这个评分动画的时候也发现了一个问题,在动画更新的监听中long currentPlayTime = valueAnimator.getCurrentPlayTime();这个方法在大部分手机没有问题,但就在华为荣耀8的7.0的手机上出现了动画不按套路出牌的效果,根据动画的效果来看发现问题出在这里,由于这里有个启动动画,这个动画就在这里乱套了,然而打印出currentPlayTime ,奇怪的是在第一次运行的时候没有任何异常,在第二次的时候currentPlayTime 的初始值不是0,而是当前动画从开始执行到现在的总共时间,用其他手机来测试,没有发现异常,再看源码里面也没有关于版本的代码,就暂时在currentPlayTime 这里判断了一下,如果大于总时间就等于0,然后再来荣耀上运行,欧拉,暂时没有问题了。</p>    <p>最后附上截图-O(∩_∩)O哈哈~</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/42ccdce19d939dbd8625e02b71b2fa56.gif"></p>    <p style="text-align:center">GIF.gif</p>    <p> </p>    <p>来自:http://www.jianshu.com/p/b8d3e833d3c9</p>    <p> </p>