1689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira/* 2689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * Copyright (C) 2014 The Android Open Source Project 3689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * 4689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 5689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * you may not use this file except in compliance with the License. 6689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * You may obtain a copy of the License at 7689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * 8689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 9689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * 10689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * Unless required by applicable law or agreed to in writing, software 11689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 12689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * See the License for the specific language governing permissions and 14689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * limitations under the License. 15689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira */ 16689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 17689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereirapackage android.support.v4.widget; 18689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 19689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.view.animation.AccelerateDecelerateInterpolator; 20689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.view.animation.Interpolator; 21689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.view.animation.Animation; 22689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.view.animation.LinearInterpolator; 23689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.view.animation.Transformation; 24689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.content.Context; 25689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.content.res.Resources; 26689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.graphics.Canvas; 27689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.graphics.Color; 28689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.graphics.ColorFilter; 29689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.graphics.Paint; 30689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.graphics.Paint.Style; 3174437a01478b39230bb5b4657b74480ede53ae94Mindy Pereiraimport android.graphics.Path; 32689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.graphics.PixelFormat; 33689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.graphics.Rect; 34689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.graphics.RectF; 35689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.graphics.drawable.Drawable; 36689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.graphics.drawable.Animatable; 37d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereiraimport android.support.annotation.IntDef; 38d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereiraimport android.support.annotation.NonNull; 39689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.util.DisplayMetrics; 40689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport android.view.View; 4174437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira 42d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereiraimport java.lang.annotation.Retention; 43d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereiraimport java.lang.annotation.RetentionPolicy; 44689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraimport java.util.ArrayList; 45689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 46689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira/** 47689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * Fancy progress indicator for Material theme. 48dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira * 49dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira * @hide 50689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira */ 51689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereiraclass MaterialProgressDrawable extends Drawable implements Animatable { 52689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); 53689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private static final Interpolator END_CURVE_INTERPOLATOR = new EndCurveInterpolator(); 54689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private static final Interpolator START_CURVE_INTERPOLATOR = new StartCurveInterpolator(); 55dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira private static final Interpolator EASE_INTERPOLATOR = new AccelerateDecelerateInterpolator(); 56689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 57d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira @Retention(RetentionPolicy.CLASS) 58dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira @IntDef({LARGE, DEFAULT}) 59d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira public @interface ProgressDrawableSize {} 60689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira // Maps to ProgressBar.Large style 61689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira static final int LARGE = 0; 62689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira // Maps to ProgressBar default style 63689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira static final int DEFAULT = 1; 64689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 65689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira // Maps to ProgressBar default style 6674437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira private static final int CIRCLE_DIAMETER = 40; 67dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira private static final float CENTER_RADIUS = 8.75f; //should add up to 10 when + stroke_width 68dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira private static final float STROKE_WIDTH = 2.5f; 69689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 70689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira // Maps to ProgressBar.Large style 71dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira private static final int CIRCLE_DIAMETER_LARGE = 56; 72dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira private static final float CENTER_RADIUS_LARGE = 12.5f; 73dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira private static final float STROKE_WIDTH_LARGE = 3f; 74689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 75689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private final int[] COLORS = new int[] { 76689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira Color.BLACK 77689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira }; 78689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 79689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira /** The duration of a single progress spin in milliseconds. */ 80689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private static final int ANIMATION_DURATION = 1000 * 80 / 60; 81689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 82689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira /** The number of points in the progress "star". */ 83689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private static final float NUM_POINTS = 5f; 84689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira /** The list of animators operating on this drawable. */ 85689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private final ArrayList<Animation> mAnimators = new ArrayList<Animation>(); 86689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 87689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira /** The indicator ring, used to manage animation state. */ 88689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private final Ring mRing; 89689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 90689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira /** Canvas rotation in degrees. */ 91689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private float mRotation; 92689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 9374437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira /** Layout info for the arrowhead in dp */ 9474437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira private static final int ARROW_WIDTH = 10; 9574437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira private static final int ARROW_HEIGHT = 5; 96dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira private static final float ARROW_OFFSET_ANGLE = 5; 97dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira 98dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira /** Layout info for the arrowhead for the large spinner in dp */ 99dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira private static final int ARROW_WIDTH_LARGE = 12; 100dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira private static final int ARROW_HEIGHT_LARGE = 6; 101dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira private static final float MAX_PROGRESS_ARC = .8f; 10274437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira 103689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private Resources mResources; 104689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private View mParent; 105689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private Animation mAnimation; 106689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private float mRotationCount; 107689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private double mWidth; 108689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private double mHeight; 109fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira boolean mFinishing; 110689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 111689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public MaterialProgressDrawable(Context context, View parent) { 112689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mParent = parent; 113689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mResources = context.getResources(); 114689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 115689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mRing = new Ring(mCallback); 116112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira mRing.setColors(COLORS); 117689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 118dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira updateSizes(DEFAULT); 119689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira setupAnimators(); 120689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 121689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 122dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira private void setSizeParameters(double progressCircleWidth, double progressCircleHeight, 123dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira double centerRadius, double strokeWidth, float arrowWidth, float arrowHeight) { 124689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira final Ring ring = mRing; 125689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira final DisplayMetrics metrics = mResources.getDisplayMetrics(); 126689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira final float screenDensity = metrics.density; 127689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 128689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mWidth = progressCircleWidth * screenDensity; 129689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mHeight = progressCircleHeight * screenDensity; 130dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira ring.setStrokeWidth((float) strokeWidth * screenDensity); 131dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira ring.setCenterRadius(centerRadius * screenDensity); 132d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira ring.setColorIndex(0); 133dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira ring.setArrowDimensions(arrowWidth * screenDensity, arrowHeight * screenDensity); 134dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira ring.setInsets((int) mWidth, (int) mHeight); 135689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 136689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 137d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 138d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * Set the overall size for the progress spinner. This updates the radius 139d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * and stroke width of the ring. 140d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * 141dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira * @param size One of {@link MaterialProgressDrawable.LARGE} or 142dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira * {@link MaterialProgressDrawable.DEFAULT} 143d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 144dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira public void updateSizes(@ProgressDrawableSize int size) { 145689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira if (size == LARGE) { 146dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira setSizeParameters(CIRCLE_DIAMETER_LARGE, CIRCLE_DIAMETER_LARGE, CENTER_RADIUS_LARGE, 147dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira STROKE_WIDTH_LARGE, ARROW_WIDTH_LARGE, ARROW_HEIGHT_LARGE); 148689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } else { 149dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira setSizeParameters(CIRCLE_DIAMETER, CIRCLE_DIAMETER, CENTER_RADIUS, STROKE_WIDTH, 150dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira ARROW_WIDTH, ARROW_HEIGHT); 151689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 152689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 153689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 154d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 155d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * @param show Set to true to display the arrowhead on the progress spinner. 156d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 15774437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira public void showArrow(boolean show) { 15874437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira mRing.setShowArrow(show); 15974437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira } 16074437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira 161d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 162d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * @param scale Set the scale of the arrowhead for the spinner. 163d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 16474437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira public void setArrowScale(float scale) { 16574437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira mRing.setArrowScale(scale); 16674437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira } 16774437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira 168d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 169d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * Set the start and end trim for the progress spinner arc. 170d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * 171d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * @param startAngle start angle 172d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * @param endAngle end angle 173d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 174d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira public void setStartEndTrim(float startAngle, float endAngle) { 175d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira mRing.setStartTrim(startAngle); 176d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira mRing.setEndTrim(endAngle); 177689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 178689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 179d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 180d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * Set the amount of rotation to apply to the progress spinner. 181d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * 182dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira * @param rotation Rotation is from [0..1] 183d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 184d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira public void setProgressRotation(float rotation) { 185d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira mRing.setRotation(rotation); 186689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 187689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 188689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira /** 189dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira * Update the background color of the circle image view. 190dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira */ 191dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira public void setBackgroundColor(int color) { 192dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mRing.setBackgroundColor(color); 193dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira } 194dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira 195dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira /** 196689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * Set the colors used in the progress animation from color resources. 197689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * The first color will also be the color of the bar that grows in response 198689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * to a user swipe gesture. 199689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * 200689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * @param colors 201689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira */ 202689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void setColorSchemeColors(int... colors) { 203112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira mRing.setColors(colors); 204112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira mRing.setColorIndex(0); 205689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 206689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 207689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 208689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public int getIntrinsicHeight() { 209689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return (int) mHeight; 210689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 211689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 212689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 213689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public int getIntrinsicWidth() { 214689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return (int) mWidth; 215689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 216689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 217689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 218689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void draw(Canvas c) { 219689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira final Rect bounds = getBounds(); 220689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira final int saveCount = c.save(); 221689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira c.rotate(mRotation, bounds.exactCenterX(), bounds.exactCenterY()); 222689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mRing.draw(c, bounds); 223689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira c.restoreToCount(saveCount); 224689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 225689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 226689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 227689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void setAlpha(int alpha) { 228689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mRing.setAlpha(alpha); 229689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 230689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 231689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public int getAlpha() { 232689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return mRing.getAlpha(); 233689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 234689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 235689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 236689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void setColorFilter(ColorFilter colorFilter) { 237689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mRing.setColorFilter(colorFilter); 238689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 239689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 240dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira @SuppressWarnings("unused") 241dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira void setRotation(float rotation) { 242689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mRotation = rotation; 243689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira invalidateSelf(); 244689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 245689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 246689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @SuppressWarnings("unused") 247689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private float getRotation() { 248689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return mRotation; 249689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 250689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 251689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 252689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public int getOpacity() { 253689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return PixelFormat.TRANSLUCENT; 254689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 255689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 256689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 257689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public boolean isRunning() { 258689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira final ArrayList<Animation> animators = mAnimators; 259689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira final int N = animators.size(); 260689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira for (int i = 0; i < N; i++) { 261689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira final Animation animator = animators.get(i); 262689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira if (animator.hasStarted() && !animator.hasEnded()) { 263689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return true; 264689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 265689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 266689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return false; 267689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 268689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 269689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 270689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void start() { 271689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mAnimation.reset(); 272689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mRing.storeOriginals(); 273dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira // Already showing some part of the ring 274dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira if (mRing.getEndTrim() != mRing.getStartTrim()) { 275fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira mFinishing = true; 276fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira mAnimation.setDuration(ANIMATION_DURATION/2); 277fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira mParent.startAnimation(mAnimation); 278689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } else { 279112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira mRing.setColorIndex(0); 280689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mRing.resetOriginals(); 281fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira mAnimation.setDuration(ANIMATION_DURATION); 282689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mParent.startAnimation(mAnimation); 283689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 284689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 285689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 286689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 287689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void stop() { 288689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mParent.clearAnimation(); 289689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira setRotation(0); 290dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira mRing.setShowArrow(false); 291112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira mRing.setColorIndex(0); 292689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mRing.resetOriginals(); 293689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 294689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 295fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira private void applyFinishTranslation(float interpolatedTime, Ring ring) { 296fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira // shrink back down and complete a full rotation before 297fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira // starting other circles 298fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira // Rotation goes between [0..1]. 299fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira float targetRotation = (float) (Math.floor(ring.getStartingRotation() / MAX_PROGRESS_ARC) 300fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira + 1f); 301fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira final float startTrim = ring.getStartingStartTrim() 302fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira + (ring.getStartingEndTrim() - ring.getStartingStartTrim()) * interpolatedTime; 303fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira ring.setStartTrim(startTrim); 304fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira final float rotation = ring.getStartingRotation() 305fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira + ((targetRotation - ring.getStartingRotation()) * interpolatedTime); 306fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira ring.setRotation(rotation); 307fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira } 308fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira 309689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private void setupAnimators() { 310689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira final Ring ring = mRing; 311689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira final Animation animation = new Animation() { 312fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira @Override 313689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void applyTransformation(float interpolatedTime, Transformation t) { 314fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira if (mFinishing) { 315fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira applyFinishTranslation(interpolatedTime, ring); 316fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira } else { 317fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira // The minProgressArc is calculated from 0 to create an 318fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira // angle that 319fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira // matches the stroke width. 320fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira final float minProgressArc = (float) Math.toRadians( 321fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira ring.getStrokeWidth() / (2 * Math.PI * ring.getCenterRadius())); 322fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira final float startingEndTrim = ring.getStartingEndTrim(); 323fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira final float startingTrim = ring.getStartingStartTrim(); 324fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira final float startingRotation = ring.getStartingRotation(); 325fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira 326fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira // Offset the minProgressArc to where the endTrim is 327fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira // located. 328fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira final float minArc = MAX_PROGRESS_ARC - minProgressArc; 329fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira final float endTrim = startingEndTrim + (minArc 330fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira * START_CURVE_INTERPOLATOR.getInterpolation(interpolatedTime)); 331fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira ring.setEndTrim(endTrim); 332fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira 333fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira final float startTrim = startingTrim + (MAX_PROGRESS_ARC 334fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira * END_CURVE_INTERPOLATOR.getInterpolation(interpolatedTime)); 335fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira ring.setStartTrim(startTrim); 336fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira 337fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira final float rotation = startingRotation + (0.25f * interpolatedTime); 338fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira ring.setRotation(rotation); 339fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira 340fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira float groupRotation = ((720.0f / NUM_POINTS) * interpolatedTime) 341fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira + (720.0f * (mRotationCount / NUM_POINTS)); 342fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira setRotation(groupRotation); 343fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira } 344689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 345689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira }; 346689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira animation.setRepeatCount(Animation.INFINITE); 347689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira animation.setRepeatMode(Animation.RESTART); 348689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira animation.setInterpolator(LINEAR_INTERPOLATOR); 349689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira animation.setAnimationListener(new Animation.AnimationListener() { 350689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 351fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira @Override 352689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void onAnimationStart(Animation animation) { 353689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mRotationCount = 0; 354689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 355689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 356fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira @Override 357689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void onAnimationEnd(Animation animation) { 358689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira // do nothing 359689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 360689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 361fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira @Override 362689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void onAnimationRepeat(Animation animation) { 363dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira ring.storeOriginals(); 364112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira ring.goToNextColor(); 365dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira ring.setStartTrim(ring.getEndTrim()); 366fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira if (mFinishing) { 367fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira // finished closing the last ring from the swipe gesture; go 368fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira // into progress mode 369fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira mFinishing = false; 370fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira animation.setDuration(ANIMATION_DURATION); 371fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira ring.setShowArrow(false); 372fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira } else { 373fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira mRotationCount = (mRotationCount + 1) % (NUM_POINTS); 374fa77943ee3d8ef33abf4f8288875783de623b4d9Mindy Pereira } 375689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 376689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira }); 377689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mAnimation = animation; 378689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 379689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 380689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private final Callback mCallback = new Callback() { 381689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 382689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void invalidateDrawable(Drawable d) { 383689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira invalidateSelf(); 384689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 385689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 386689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 387689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void scheduleDrawable(Drawable d, Runnable what, long when) { 388689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira scheduleSelf(what, when); 389689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 390689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 391689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 392689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void unscheduleDrawable(Drawable d, Runnable what) { 393689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira unscheduleSelf(what); 394689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 395689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira }; 396689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 397689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private static class Ring { 398689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private final RectF mTempBounds = new RectF(); 399689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private final Paint mPaint = new Paint(); 40074437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira private final Paint mArrowPaint = new Paint(); 401689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 402689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private final Callback mCallback; 403689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 404689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private float mStartTrim = 0.0f; 405689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private float mEndTrim = 0.0f; 406689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private float mRotation = 0.0f; 407689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private float mStrokeWidth = 5.0f; 408689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private float mStrokeInset = 2.5f; 409689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 410689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private int[] mColors; 411dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira // mColorIndex represents the offset into the available mColors that the 412dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira // progress circle should currently display. As the progress circle is 413dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira // animating, the mColorIndex moves by one to the next available color. 414689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private int mColorIndex; 415689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private float mStartingStartTrim; 416689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private float mStartingEndTrim; 417689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private float mStartingRotation; 41874437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira private boolean mShowArrow; 41974437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira private Path mArrow; 42074437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira private float mArrowScale; 421dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira private double mRingCenterRadius; 42274437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira private int mArrowWidth; 42374437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira private int mArrowHeight; 424dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira private int mAlpha; 425dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira private final Paint mCirclePaint = new Paint(); 426dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira private int mBackgroundColor; 427689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 428689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public Ring(Callback callback) { 429689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mCallback = callback; 430689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 4314221e345d86111915467679815ead8888da5e2f4Mindy Pereira mPaint.setStrokeCap(Paint.Cap.SQUARE); 432689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mPaint.setAntiAlias(true); 433689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mPaint.setStyle(Style.STROKE); 43474437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira 435dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mArrowPaint.setStyle(Paint.Style.FILL); 43674437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira mArrowPaint.setAntiAlias(true); 437689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 438689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 439dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira public void setBackgroundColor(int color) { 440dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mBackgroundColor = color; 441dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira } 442dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira 443689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira /** 444dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira * Set the dimensions of the arrowhead. 445dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira * 446dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira * @param width Width of the hypotenuse of the arrow head 447dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira * @param height Height of the arrow point 448dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira */ 449dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira public void setArrowDimensions(float width, float height) { 450dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira mArrowWidth = (int) width; 451dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira mArrowHeight = (int) height; 452dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira } 453dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira 454dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira /** 455d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * Draw the progress spinner 456689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira */ 457689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void draw(Canvas c, Rect bounds) { 458689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira final RectF arcBounds = mTempBounds; 459689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira arcBounds.set(bounds); 460689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira arcBounds.inset(mStrokeInset, mStrokeInset); 461689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 462689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira final float startAngle = (mStartTrim + mRotation) * 360; 463689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira final float endAngle = (mEndTrim + mRotation) * 360; 464689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira float sweepAngle = endAngle - startAngle; 465689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 466689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mPaint.setColor(mColors[mColorIndex]); 467689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira c.drawArc(arcBounds, startAngle, sweepAngle, false, mPaint); 46874437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira 469dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira drawTriangle(c, startAngle, sweepAngle, bounds); 470dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira 471dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira if (mAlpha < 255) { 472dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mCirclePaint.setColor(mBackgroundColor); 473dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mCirclePaint.setAlpha(255 - mAlpha); 474dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira c.drawCircle(bounds.exactCenterX(), bounds.exactCenterY(), bounds.width() / 2, 475dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mCirclePaint); 47674437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira } 477dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira } 47874437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira 479dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira private void drawTriangle(Canvas c, float startAngle, float sweepAngle, Rect bounds) { 48074437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira if (mShowArrow) { 481dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira if (mArrow == null) { 482dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mArrow = new android.graphics.Path(); 483dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mArrow.setFillType(android.graphics.Path.FillType.EVEN_ODD); 484dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira } else { 485dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mArrow.reset(); 48674437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira } 487dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira 488dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira // Adjust the position of the triangle so that it is inset as 489dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira // much as the arc, but also centered on the arc. 490c39bdbe9d24491caf92194229393ff58c16aed7fMindy Pereira float inset = (int) mStrokeInset / 2 * mArrowScale; 491dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira float x = (float) (mRingCenterRadius * Math.cos(0) + bounds.exactCenterX()); 492dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira float y = (float) (mRingCenterRadius * Math.sin(0) + bounds.exactCenterY()); 493dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira 494dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira // Update the path each time. This works around an issue in SKIA 495dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira // where concatenating a rotation matrix to a scale matrix 496dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira // ignored a starting negative rotation. This appears to have 497dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira // been fixed as of API 21. 498dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mArrow.moveTo(0, 0); 499dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mArrow.lineTo(mArrowWidth * mArrowScale, 0); 500dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mArrow.lineTo((mArrowWidth * mArrowScale / 2), (mArrowHeight 501dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira * mArrowScale)); 502dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mArrow.offset(x - inset, y); 503dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mArrow.close(); 504dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira // draw a triangle 50574437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira mArrowPaint.setColor(mColors[mColorIndex]); 506dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira c.rotate(startAngle + sweepAngle - ARROW_OFFSET_ANGLE, bounds.exactCenterX(), 507dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira bounds.exactCenterY()); 508dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira c.drawPath(mArrow, mArrowPaint); 50974437a01478b39230bb5b4657b74480ede53ae94Mindy Pereira } 510689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 511689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 512d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 513d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * Set the colors the progress spinner alternates between. 514d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * 515d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * @param colors Array of integers describing the colors. Must be non-<code>null</code>. 516d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 517d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira public void setColors(@NonNull int[] colors) { 518689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mColors = colors; 519112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira // if colors are reset, make sure to reset the color index as well 520112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira setColorIndex(0); 521689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 522689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 523d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 524d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * @param index Index into the color array of the color to display in 525d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * the progress spinner. 526d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 527689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void setColorIndex(int index) { 528689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mColorIndex = index; 529689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 530689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 531112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira /** 532112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira * Proceed to the next available ring color. This will automatically 533112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira * wrap back to the beginning of colors. 534112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira */ 535112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira public void goToNextColor() { 536112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira mColorIndex = (mColorIndex + 1) % (mColors.length); 537112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira } 538112ae3627e7f32991822b3fd2001fe7239f1d3eaMindy Pereira 539689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void setColorFilter(ColorFilter filter) { 540689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mPaint.setColorFilter(filter); 541689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira invalidateSelf(); 542689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 543689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 544d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 545d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * @param alpha Set the alpha of the progress spinner and associated arrowhead. 546d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 547689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void setAlpha(int alpha) { 548dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mAlpha = alpha; 549689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 550689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 551d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 552d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * @return Current alpha of the progress spinner and arrowhead. 553d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 554689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public int getAlpha() { 555dc943d6192dab40df68b6b583c84e64045ea1bc8Mindy Pereira return mAlpha; 556689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 557689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 558d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 559d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * @param strokeWidth Set the stroke width of the progress spinner in pixels. 560d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 561689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void setStrokeWidth(float strokeWidth) { 562689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mStrokeWidth = strokeWidth; 563689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mPaint.setStrokeWidth(strokeWidth); 564689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira invalidateSelf(); 565689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 566689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 567689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @SuppressWarnings("unused") 568689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public float getStrokeWidth() { 569689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return mStrokeWidth; 570689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 571689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 572689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @SuppressWarnings("unused") 573689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void setStartTrim(float startTrim) { 574689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mStartTrim = startTrim; 575689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira invalidateSelf(); 576689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 577689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 578689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @SuppressWarnings("unused") 579689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public float getStartTrim() { 580689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return mStartTrim; 581689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 582689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 583689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public float getStartingStartTrim() { 584689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return mStartingStartTrim; 585689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 586689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 587689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public float getStartingEndTrim() { 588689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return mStartingEndTrim; 589689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 590689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 591689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @SuppressWarnings("unused") 592689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void setEndTrim(float endTrim) { 593689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mEndTrim = endTrim; 594689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira invalidateSelf(); 595689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 596689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 597689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @SuppressWarnings("unused") 598689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public float getEndTrim() { 599689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return mEndTrim; 600689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 601689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 602689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @SuppressWarnings("unused") 603689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public void setRotation(float rotation) { 604689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mRotation = rotation; 605689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira invalidateSelf(); 606689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 607689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 608689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @SuppressWarnings("unused") 609689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public float getRotation() { 610689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return mRotation; 611689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 612689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 613dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira public void setInsets(int width, int height) { 614dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira final float minEdge = (float) Math.min(width, height); 615dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira float insets; 616dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira if (mRingCenterRadius <= 0 || minEdge < 0) { 617dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira insets = (float) Math.ceil(mStrokeWidth / 2.0f); 618dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira } else { 619dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira insets = (float) (minEdge / 2.0f - mRingCenterRadius); 620dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira } 621689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mStrokeInset = insets; 622689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 623689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 624689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @SuppressWarnings("unused") 625689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public float getInsets() { 626689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return mStrokeInset; 627689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 628689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 629d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 630dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira * @param centerRadius Inner radius in px of the circle the progress 631d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * spinner arc traces. 632d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 633dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira public void setCenterRadius(double centerRadius) { 634dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira mRingCenterRadius = centerRadius; 635dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira } 636dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira 637dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira public double getCenterRadius() { 638dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira return mRingCenterRadius; 639d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira } 640d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira 641d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 642d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * @param show Set to true to show the arrow head on the progress spinner. 643d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 644d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira public void setShowArrow(boolean show) { 645d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira if (mShowArrow != show) { 646d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira mShowArrow = show; 647d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira invalidateSelf(); 648d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira } 649d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira } 650d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira 651d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 652d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * @param scale Set the scale of the arrowhead for the spinner. 653d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 654d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira public void setArrowScale(float scale) { 655d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira if (scale != mArrowScale) { 656d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira mArrowScale = scale; 657d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira invalidateSelf(); 658d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira } 659d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira } 660d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira 661d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 662dd27d55a5152f86c07758067e587bdd5b719abafMindy Pereira * @return The amount the progress spinner is currently rotated, between [0..1]. 663d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 664d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira public float getStartingRotation() { 665d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira return mStartingRotation; 666d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira } 667d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira 668d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 669d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * If the start / end trim are offset to begin with, store them so that 670d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * animation starts from that offset. 671d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 672d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira public void storeOriginals() { 673d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira mStartingStartTrim = mStartTrim; 674d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira mStartingEndTrim = mEndTrim; 675d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira mStartingRotation = mRotation; 676d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira } 677d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira 678d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira /** 679d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira * Reset the progress spinner to default rotation, start and end angles. 680d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira */ 681d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira public void resetOriginals() { 682d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira mStartingStartTrim = 0; 683d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira mStartingEndTrim = 0; 684d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira mStartingRotation = 0; 685d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira setStartTrim(0); 686d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira setEndTrim(0); 687d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira setRotation(0); 688d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira } 689d08402a890f1ac4d3de832a9a781cbc5ebde804fMindy Pereira 690689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private void invalidateSelf() { 691689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira mCallback.invalidateDrawable(null); 692689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 693689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 694689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 695689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira /** 696689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * Squishes the interpolation curve into the second half of the animation. 697689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira */ 698689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private static class EndCurveInterpolator extends AccelerateDecelerateInterpolator { 699689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 700689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public float getInterpolation(float input) { 701689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return super.getInterpolation(Math.max(0, (input - 0.5f) * 2.0f)); 702689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 703689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 704689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira 705689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira /** 706689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira * Squishes the interpolation curve into the first half of the animation. 707689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira */ 708689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira private static class StartCurveInterpolator extends AccelerateDecelerateInterpolator { 709689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira @Override 710689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira public float getInterpolation(float input) { 711689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira return super.getInterpolation(Math.min(1, input * 2.0f)); 712689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 713689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira } 714689ab224266f62aefb35ef0b80af6edf66eb8972Mindy Pereira} 715