summaryrefslogtreecommitdiffstats
path: root/src/android/support/wearable/view/ProgressDrawable.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/android/support/wearable/view/ProgressDrawable.java')
-rw-r--r--src/android/support/wearable/view/ProgressDrawable.java176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/android/support/wearable/view/ProgressDrawable.java b/src/android/support/wearable/view/ProgressDrawable.java
new file mode 100644
index 00000000..63e6a039
--- /dev/null
+++ b/src/android/support/wearable/view/ProgressDrawable.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.support.wearable.view;
+
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.annotation.TargetApi;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.util.Property;
+import android.view.animation.LinearInterpolator;
+
+/**
+ * Drawable for showing an indeterminate progress indicator.
+ *
+ * TODO: When Material progress drawable is available in the support library stop using this.
+ *
+ * @hide
+ */
+@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
+class ProgressDrawable extends Drawable {
+
+ private static Property<ProgressDrawable, Integer> LEVEL =
+ new Property<ProgressDrawable, Integer>(Integer.class, "level") {
+ @Override
+ public Integer get(ProgressDrawable drawable) {
+ return drawable.getLevel();
+ }
+
+ @Override
+ public void set(ProgressDrawable drawable, Integer value) {
+ drawable.setLevel(value);
+ drawable.invalidateSelf();
+ }
+ };
+ /** Max level for a level drawable, as specified in developer docs for {@link Drawable}. */
+ private static final int MAX_LEVEL = 10000;
+
+ /** How many different sections are there, five gives us the material style star. **/
+ private static final int NUMBER_OF_SEGMENTS = 5;
+
+ private static final int LEVELS_PER_SEGMENT = MAX_LEVEL / NUMBER_OF_SEGMENTS;
+ private static final float STARTING_ANGLE = -90f;
+ private static final long ANIMATION_DURATION = 6000;
+ private static final int FULL_CIRCLE = 360;
+ private static final int MAX_SWEEP = 306;
+ private static final int CORRECTION_ANGLE = FULL_CIRCLE - MAX_SWEEP;
+ /** How far through each cycle does the bar stop growing and start shrinking, half way. **/
+ private static final float GROW_SHRINK_RATIO = 0.5f;
+ // TODO: replace this with BakedBezierInterpolator when its available in support library.
+ private static final TimeInterpolator mInterpolator = Gusterpolator.INSTANCE;
+
+ private final RectF mInnerCircleBounds = new RectF();
+ private final Paint mPaint = new Paint();
+ private final ObjectAnimator mAnimator;
+ private float mCircleBorderWidth;
+ private int mCircleBorderColor;
+
+ public ProgressDrawable() {
+ mPaint.setAntiAlias(true);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mAnimator = ObjectAnimator.ofInt(this, LEVEL, 0, MAX_LEVEL);
+ mAnimator.setRepeatCount(ValueAnimator.INFINITE);
+ mAnimator.setRepeatMode(ValueAnimator.RESTART);
+ mAnimator.setDuration(ANIMATION_DURATION);
+ mAnimator.setInterpolator(new LinearInterpolator());
+ }
+
+ public void setRingColor(int color) {
+ mCircleBorderColor = color;
+ }
+
+ public void setRingWidth(float width) {
+ mCircleBorderWidth = width;
+ }
+
+ public void startAnimation() {
+ mAnimator.start();
+ }
+
+ public void stopAnimation() {
+ mAnimator.cancel();
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ canvas.save();
+ mInnerCircleBounds.set(getBounds());
+ mInnerCircleBounds.inset(mCircleBorderWidth / 2.0f, mCircleBorderWidth / 2.0f);
+ mPaint.setStrokeWidth(mCircleBorderWidth);
+ mPaint.setColor(mCircleBorderColor);
+
+ float sweepAngle = FULL_CIRCLE;
+ boolean growing = false;
+ float correctionAngle = 0;
+ int level = getLevel();
+
+ int currentSegment = level / LEVELS_PER_SEGMENT;
+ int offset = currentSegment * LEVELS_PER_SEGMENT;
+ float progress = (level - offset) / (float) LEVELS_PER_SEGMENT;
+
+ growing = progress < GROW_SHRINK_RATIO;
+ correctionAngle = CORRECTION_ANGLE * progress;
+
+ if (growing) {
+ sweepAngle = MAX_SWEEP * mInterpolator.getInterpolation(
+ lerpInv(0f, GROW_SHRINK_RATIO, progress));
+ } else {
+ sweepAngle = MAX_SWEEP * (1.0f - mInterpolator.getInterpolation(
+ lerpInv(GROW_SHRINK_RATIO, 1.0f, progress)));
+ }
+
+ sweepAngle = Math.max(1, sweepAngle);
+
+ canvas.rotate(
+ level * (1.0f / MAX_LEVEL) * 2 * FULL_CIRCLE + STARTING_ANGLE + correctionAngle,
+ mInnerCircleBounds.centerX(),
+ mInnerCircleBounds.centerY());
+ canvas.drawArc(mInnerCircleBounds,
+ growing ? 0 : MAX_SWEEP - sweepAngle,
+ sweepAngle,
+ false,
+ mPaint);
+ canvas.restore();
+ }
+
+ @Override
+ public void setAlpha(int i) {
+ // Not supported.
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ // Not supported.
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.OPAQUE;
+ }
+
+ @Override
+ protected boolean onLevelChange(int level) {
+ return true; // Changing the level of this drawable does change its appearance.
+ }
+
+ /**
+ * Returns the interpolation scalar (s) that satisfies the equation:
+ * {@code value = }lerp(a, b, s)
+ *
+ * <p>If {@code a == b}, then this function will return 0.
+ */
+ private static float lerpInv(float a, float b, float value) {
+ return a != b ? ((value - a) / (b - a)) : 0.0f;
+ }
+}