CircularProgressDrawable.java

public class CircularProgressDrawable extends Drawable
    implements Animatable {
 
  private static final Interpolator ANGLE_INTERPOLATOR      = new LinearInterpolator();
  private static final Interpolator SWEEP_INTERPOLATOR      = new DecelerateInterpolator();
  private static final int          ANGLE_ANIMATOR_DURATION = 2000;
  private static final int          SWEEP_ANIMATOR_DURATION = 600;
  private static final int          MIN_SWEEP_ANGLE         = 30;
  private final        RectF        fBounds                 = new RectF();
 
  private ObjectAnimator mObjectAnimatorSweep;
  private ObjectAnimator mObjectAnimatorAngle;
  private boolean        mModeAppearing;
  private Paint          mPaint;
  private float          mCurrentGlobalAngleOffset;
  private float          mCurrentGlobalAngle;
  private float          mCurrentSweepAngle;
  private float          mBorderWidth;
  private boolean        mRunning;
 
  public CircularProgressDrawable(int color, float borderWidth) {
    mBorderWidth = borderWidth;
 
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeWidth(borderWidth);
    mPaint.setColor(color);
 
    setupAnimations();
  }
 
  @Override
  public void draw(Canvas canvas) {
    float startAngle = mCurrentGlobalAngle - mCurrentGlobalAngleOffset;
    float sweepAngle = mCurrentSweepAngle;
    if (!mModeAppearing) {
      startAngle = startAngle + sweepAngle;
      sweepAngle = 360 - sweepAngle - MIN_SWEEP_ANGLE;
    } else {
      sweepAngle += MIN_SWEEP_ANGLE;
    }
    canvas.drawArc(fBounds, startAngle, sweepAngle, false, mPaint);
  }
 
  @Override
  public void setAlpha(int alpha) {
    mPaint.setAlpha(alpha);
  }
 
  @Override
  public void setColorFilter(ColorFilter cf) {
    mPaint.setColorFilter(cf);
  }
 
  @Override
  public int getOpacity() {
    return PixelFormat.TRANSPARENT;
  }
 
  private void toggleAppearingMode() {
    mModeAppearing = !mModeAppearing;
    if (mModeAppearing) {
      mCurrentGlobalAngleOffset = (mCurrentGlobalAngleOffset + MIN_SWEEP_ANGLE * 2) % 360;
    }
  }
 
  @Override
  protected void onBoundsChange(Rect bounds) {
    super.onBoundsChange(bounds);
    fBounds.left = bounds.left + mBorderWidth / 2f + .5f;
    fBounds.right = bounds.right - mBorderWidth / 2f - .5f;
    fBounds.top = bounds.top + mBorderWidth / 2f + .5f;
    fBounds.bottom = bounds.bottom - mBorderWidth / 2f - .5f;
  }
 
  //
              Animation
 
  private Property<SmoothCircularIndeterminateProgressBarDrawable, Float> mAngleProperty
      = new Property<SmoothCircularIndeterminateProgressBarDrawable, Float>(Float.class, "angle") {
    @Override
    public Float get(SmoothCircularIndeterminateProgressBarDrawable object) {
      return object.getCurrentGlobalAngle();
    }
 
    @Override
    public void set(SmoothCircularIndeterminateProgressBarDrawable object, Float value) {
      object.setCurrentGlobalAngle(value);
    }
  };
 
  private Property<SmoothCircularIndeterminateProgressBarDrawable, Float> mSweepProperty
      = new Property<SmoothCircularIndeterminateProgressBarDrawable, Float>(Float.class, "arc") {
    @Override
    public Float get(SmoothCircularIndeterminateProgressBarDrawable object) {
      return object.getCurrentSweepAngle();
    }
 
    @Override
    public void set(SmoothCircularIndeterminateProgressBarDrawable object, Float value) {
      object.setCurrentSweepAngle(value);
    }
  };
 
  private void setupAnimations() {
    mObjectAnimatorAngle = ObjectAnimator.ofFloat(this, mAngleProperty, 360f);
    mObjectAnimatorAngle.setInterpolator(ANGLE_INTERPOLATOR);
    mObjectAnimatorAngle.setDuration(ANGLE_ANIMATOR_DURATION);
    mObjectAnimatorAngle.setRepeatMode(ValueAnimator.RESTART);
    mObjectAnimatorAngle.setRepeatCount(ValueAnimator.INFINITE);
 
    mObjectAnimatorSweep = ObjectAnimator.ofFloat(this, mSweepProperty, 360f - MIN_SWEEP_ANGLE * 2);
    mObjectAnimatorSweep.setInterpolator(SWEEP_INTERPOLATOR);
    mObjectAnimatorSweep.setDuration(SWEEP_ANIMATOR_DURATION);
    mObjectAnimatorSweep.setRepeatMode(ValueAnimator.RESTART);
    mObjectAnimatorSweep.setRepeatCount(ValueAnimator.INFINITE);
    mObjectAnimatorSweep.addListener(new Animator.AnimatorListener() {
      @Override
      public void onAnimationStart(Animator animation) {
 
      }
 
      @Override
      public void onAnimationEnd(Animator animation) {
 
      }
 
      @Override
      public void onAnimationCancel(Animator animation) {
 
      }
 
      @Override
      public void onAnimationRepeat(Animator animation) {
        toggleAppearingMode();
      }
    });
  }
 
  @Override
  public void start() {
    if (isRunning()) {
      return;
    }
    mRunning = true;
    mObjectAnimatorAngle.start();
    mObjectAnimatorSweep.start();
    invalidateSelf();
  }
 
  @Override
  public void stop() {
    if (!isRunning()) {
      return;
    }
    mRunning = false;
    mObjectAnimatorAngle.cancel();
    mObjectAnimatorSweep.cancel();
    invalidateSelf();
  }
 
  @Override
  public boolean isRunning() {
    return mRunning;
  }
 
  public void setCurrentGlobalAngle(float currentGlobalAngle) {
    mCurrentGlobalAngle = currentGlobalAngle;
    invalidateSelf();
  }
 
  public float getCurrentGlobalAngle() {
    return mCurrentGlobalAngle;
  }
 
  public void setCurrentSweepAngle(float currentSweepAngle) {
    mCurrentSweepAngle = currentSweepAngle;
    invalidateSelf();
  }
 
  public float getCurrentSweepAngle() {
    return mCurrentSweepAngle;
  }
 
}

3772327637976360306.gif

转载于:https://my.oschina.net/oppo4545/blog/316842

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值