SwipeProgressBar.java revision 4d2c7b7c4f194034c5f17c4bee7320d808aabe4c
1e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira/*
2e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * Copyright (C) 2013 The Android Open Source Project
3e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira *
4e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License");
5e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * you may not use this file except in compliance with the License.
6e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * You may obtain a copy of the License at
7e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira *
8e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira *      http://www.apache.org/licenses/LICENSE-2.0
9e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira *
10e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * Unless required by applicable law or agreed to in writing, software
11e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS,
12e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * See the License for the specific language governing permissions and
14e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * limitations under the License.
15e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira */
16e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
17e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereirapackage android.support.v4.widget;
18e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
19e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereiraimport android.graphics.Canvas;
20e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereiraimport android.graphics.Paint;
21e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereiraimport android.graphics.Rect;
22e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereiraimport android.graphics.RectF;
23e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereiraimport android.support.v4.view.ViewCompat;
247c2e72c6d0a01e42d8039a09116bc35326d8acfbChris Banesimport android.support.v4.view.animation.FastOutSlowInInterpolator;
25e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereiraimport android.view.View;
26e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereiraimport android.view.animation.AnimationUtils;
27e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereiraimport android.view.animation.Interpolator;
28e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
29e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
30e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira/**
31e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * Custom progress bar that shows a cycle of colors as widening circles that
32e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * overdraw each other. When finished, the bar is cleared from the inside out as
33e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * the main cycle continues. Before running, this can also indicate how close
34e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * the user is to triggering something (e.g. how far they need to pull down to
35e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira * trigger a refresh).
36e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira */
37e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereirafinal class SwipeProgressBar {
38e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
39e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    // Default progress animation colors are grays.
404d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas    private static final int COLOR1 = 0xB3000000;
414d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas    private static final int COLOR2 = 0x80000000;
424d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas    private static final int COLOR3 = 0x4d000000;
434d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas    private static final int COLOR4 = 0x1a000000;
44e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
45e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    // The duration of the animation cycle.
46e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private static final int ANIMATION_DURATION_MS = 2000;
47e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
48e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    // The duration of the animation to clear the bar.
49e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private static final int FINISH_ANIMATION_DURATION_MS = 1000;
50e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
51e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    // Interpolator for varying the speed of the animation.
527c2e72c6d0a01e42d8039a09116bc35326d8acfbChris Banes    private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();
53e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
54e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private final Paint mPaint = new Paint();
55e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private final RectF mClipRect = new RectF();
56e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private float mTriggerPercentage;
57e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private long mStartTime;
58e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private long mFinishTime;
59e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private boolean mRunning;
60e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
61e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    // Colors used when rendering the animation,
62e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private int mColor1;
63e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private int mColor2;
64e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private int mColor3;
65e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private int mColor4;
66e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private View mParent;
67e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
68e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private Rect mBounds = new Rect();
69e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
704d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas    SwipeProgressBar(View parent) {
71e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mParent = parent;
72e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mColor1 = COLOR1;
73e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mColor2 = COLOR2;
74e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mColor3 = COLOR3;
75e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mColor4 = COLOR4;
76e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    }
77e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
78e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    /**
79e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * Set the four colors used in the progress animation. The first color will
80e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * also be the color of the bar that grows in response to a user swipe
81e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * gesture.
82e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     *
83e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * @param color1 Integer representation of a color.
84e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * @param color2 Integer representation of a color.
85e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * @param color3 Integer representation of a color.
86e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * @param color4 Integer representation of a color.
87e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     */
88e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    void setColorScheme(int color1, int color2, int color3, int color4) {
89e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mColor1 = color1;
90e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mColor2 = color2;
91e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mColor3 = color3;
92e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mColor4 = color4;
93e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    }
94e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
95e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    /**
96e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * Update the progress the user has made toward triggering the swipe
97e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * gesture. and use this value to update the percentage of the trigger that
98e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * is shown.
99e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     */
100e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    void setTriggerPercentage(float triggerPercentage) {
101e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mTriggerPercentage = triggerPercentage;
102e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mStartTime = 0;
1035dc9e705fad3b6a0e0ceedb8cb8cee9e6716802fAlan Viverette        ViewCompat.postInvalidateOnAnimation(
1045dc9e705fad3b6a0e0ceedb8cb8cee9e6716802fAlan Viverette                mParent, mBounds.left, mBounds.top, mBounds.right, mBounds.bottom);
105e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    }
106e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
107e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    /**
108e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * Start showing the progress animation.
109e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     */
110e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    void start() {
111e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        if (!mRunning) {
112e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            mTriggerPercentage = 0;
113e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            mStartTime = AnimationUtils.currentAnimationTimeMillis();
114e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            mRunning = true;
115e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            mParent.postInvalidate();
116e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        }
117e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    }
118e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
119e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    /**
120e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * Stop showing the progress animation.
121e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     */
122e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    void stop() {
123e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        if (mRunning) {
124e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            mTriggerPercentage = 0;
125e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            mFinishTime = AnimationUtils.currentAnimationTimeMillis();
126e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            mRunning = false;
127e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            mParent.postInvalidate();
128e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        }
129e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    }
130e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
131e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    /**
132e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * @return Return whether the progress animation is currently running.
133e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     */
134e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    boolean isRunning() {
135e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        return mRunning || mFinishTime > 0;
136e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    }
137e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
138e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    void draw(Canvas canvas) {
139e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        final int width = mBounds.width();
140e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        final int height = mBounds.height();
141e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        final int cx = width / 2;
142ca9e92293ff32b4a8a15513b0a7afe42c127cdb7Andrew Flynn        final int cy = height / 2;
143c7f272243076297526887a3bbccf7a0ec51cc30aMindy Pereira        boolean drawTriggerWhileFinishing = false;
144e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        int restoreCount = canvas.save();
145e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        canvas.clipRect(mBounds);
146e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
147e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        if (mRunning || (mFinishTime > 0)) {
148e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            long now = AnimationUtils.currentAnimationTimeMillis();
149e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            long elapsed = (now - mStartTime) % ANIMATION_DURATION_MS;
150e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            long iterations = (now - mStartTime) / ANIMATION_DURATION_MS;
151e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            float rawProgress = (elapsed / (ANIMATION_DURATION_MS / 100f));
152e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
153e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            // If we're not running anymore, that means we're running through
154e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            // the finish animation.
155e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            if (!mRunning) {
156e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                // If the finish animation is done, don't draw anything, and
157e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                // don't repost.
158e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                if ((now - mFinishTime) >= FINISH_ANIMATION_DURATION_MS) {
159e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                    mFinishTime = 0;
160e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                    return;
161e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                }
162e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
163e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                // Otherwise, use a 0 opacity alpha layer to clear the animation
164e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                // from the inside out. This layer will prevent the circles from
165e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                // drawing within its bounds.
166e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                long finishElapsed = (now - mFinishTime) % FINISH_ANIMATION_DURATION_MS;
167e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                float finishProgress = (finishElapsed / (FINISH_ANIMATION_DURATION_MS / 100f));
168e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                float pct = (finishProgress / 100f);
169e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                // Radius of the circle is half of the screen.
170e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                float clearRadius = width / 2 * INTERPOLATOR.getInterpolation(pct);
171e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                mClipRect.set(cx - clearRadius, 0, cx + clearRadius, height);
172e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                canvas.saveLayerAlpha(mClipRect, 0, 0);
173c7f272243076297526887a3bbccf7a0ec51cc30aMindy Pereira                // Only draw the trigger if there is a space in the center of
174c7f272243076297526887a3bbccf7a0ec51cc30aMindy Pereira                // this refreshing view that needs to be filled in by the
175c7f272243076297526887a3bbccf7a0ec51cc30aMindy Pereira                // trigger. If the progress view is just still animating, let it
176c7f272243076297526887a3bbccf7a0ec51cc30aMindy Pereira                // continue animating.
177c7f272243076297526887a3bbccf7a0ec51cc30aMindy Pereira                drawTriggerWhileFinishing = true;
178e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            }
179e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
180e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            // First fill in with the last color that would have finished drawing.
181e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            if (iterations == 0) {
182e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                canvas.drawColor(mColor1);
183e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            } else {
184e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                if (rawProgress >= 0 && rawProgress < 25) {
185e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                    canvas.drawColor(mColor4);
186e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                } else if (rawProgress >= 25 && rawProgress < 50) {
187e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                    canvas.drawColor(mColor1);
188e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                } else if (rawProgress >= 50 && rawProgress < 75) {
189e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                    canvas.drawColor(mColor2);
190e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                } else {
191e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                    canvas.drawColor(mColor3);
192e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                }
193e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            }
194e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
195e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            // Then draw up to 4 overlapping concentric circles of varying radii, based on how far
196e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            // along we are in the cycle.
197e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            // progress 0-50 draw mColor2
198e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            // progress 25-75 draw mColor3
199e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            // progress 50-100 draw mColor4
200e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            // progress 75 (wrap to 25) draw mColor1
201e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            if ((rawProgress >= 0 && rawProgress <= 25)) {
202e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                float pct = (((rawProgress + 25) * 2) / 100f);
203e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                drawCircle(canvas, cx, cy, mColor1, pct);
204e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            }
205e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            if (rawProgress >= 0 && rawProgress <= 50) {
206e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                float pct = ((rawProgress * 2) / 100f);
207e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                drawCircle(canvas, cx, cy, mColor2, pct);
208e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            }
209e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            if (rawProgress >= 25 && rawProgress <= 75) {
210e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                float pct = (((rawProgress - 25) * 2) / 100f);
211e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                drawCircle(canvas, cx, cy, mColor3, pct);
212e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            }
213e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            if (rawProgress >= 50 && rawProgress <= 100) {
214e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                float pct = (((rawProgress - 50) * 2) / 100f);
215e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                drawCircle(canvas, cx, cy, mColor4, pct);
216e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            }
217e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            if ((rawProgress >= 75 && rawProgress <= 100)) {
218e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                float pct = (((rawProgress - 75) * 2) / 100f);
219e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                drawCircle(canvas, cx, cy, mColor1, pct);
220e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            }
221c7f272243076297526887a3bbccf7a0ec51cc30aMindy Pereira            if (mTriggerPercentage > 0 && drawTriggerWhileFinishing) {
222e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                // There is some portion of trigger to draw. Restore the canvas,
223e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                // then draw the trigger. Otherwise, the trigger does not appear
224e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                // until after the bar has finished animating and appears to
225e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                // just jump in at a larger width than expected.
226e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                canvas.restoreToCount(restoreCount);
227e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                restoreCount = canvas.save();
228e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                canvas.clipRect(mBounds);
229e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                drawTrigger(canvas, cx, cy);
230e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            }
231e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            // Keep running until we finish out the last cycle.
2325dc9e705fad3b6a0e0ceedb8cb8cee9e6716802fAlan Viverette            ViewCompat.postInvalidateOnAnimation(
2335dc9e705fad3b6a0e0ceedb8cb8cee9e6716802fAlan Viverette                    mParent, mBounds.left, mBounds.top, mBounds.right, mBounds.bottom);
234e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        } else {
235e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            // Otherwise if we're in the middle of a trigger, draw that.
236e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            if (mTriggerPercentage > 0 && mTriggerPercentage <= 1.0) {
237e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira                drawTrigger(canvas, cx, cy);
238e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira            }
239e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        }
240e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        canvas.restoreToCount(restoreCount);
241e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    }
242e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
243e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private void drawTrigger(Canvas canvas, int cx, int cy) {
244e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mPaint.setColor(mColor1);
245e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        canvas.drawCircle(cx, cy, cx * mTriggerPercentage, mPaint);
246e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    }
247e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
248e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    /**
249e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * Draws a circle centered in the view.
250e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     *
251e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * @param canvas the canvas to draw on
252e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * @param cx the center x coordinate
253e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * @param cy the center y coordinate
254e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * @param color the color to draw
255e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * @param pct the percentage of the view that the circle should cover
256e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     */
257e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    private void drawCircle(Canvas canvas, float cx, float cy, int color, float pct) {
258e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mPaint.setColor(color);
259e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        canvas.save();
260e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        canvas.translate(cx, cy);
261e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        float radiusScale = INTERPOLATOR.getInterpolation(pct);
262e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        canvas.scale(radiusScale, radiusScale);
263e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        canvas.drawCircle(0, 0, cx, mPaint);
264e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        canvas.restore();
265e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    }
266e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira
267e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    /**
268e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     * Set the drawing bounds of this SwipeProgressBar.
269e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira     */
270e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    void setBounds(int left, int top, int right, int bottom) {
271e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mBounds.left = left;
272e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mBounds.top = top;
273e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mBounds.right = right;
274e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira        mBounds.bottom = bottom;
275e9a361cf082bf8fbe908d1abfdc327209ec01d82Mindy Pereira    }
2764d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas}
277