1f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen/*
2f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * Copyright (C) 2006 The Android Open Source Project
3f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
4f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * Licensed under the Apache License, Version 2.0 (the "License");
5f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * you may not use this file except in compliance with the License.
6f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * You may obtain a copy of the License at
7f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
8f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *      http://www.apache.org/licenses/LICENSE-2.0
9f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
10f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * Unless required by applicable law or agreed to in writing, software
11f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * distributed under the License is distributed on an "AS IS" BASIS,
12f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * See the License for the specific language governing permissions and
14f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * limitations under the License.
15f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen */
16f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
17f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenpackage com.android.musicfx.seekbar;
18f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
19f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport com.android.internal.R;
20f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
21f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.content.Context;
22f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.content.res.TypedArray;
23f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.Bitmap;
24f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.BitmapShader;
25f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.Canvas;
26f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.Rect;
27f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.Shader;
28f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.drawable.Animatable;
29f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.drawable.AnimationDrawable;
30f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.drawable.BitmapDrawable;
31f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.drawable.ClipDrawable;
32f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.drawable.Drawable;
33f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.drawable.LayerDrawable;
34f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.drawable.ShapeDrawable;
35f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.drawable.StateListDrawable;
36f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.drawable.shapes.RoundRectShape;
37f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.graphics.drawable.shapes.Shape;
38f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.os.Parcel;
39f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.os.Parcelable;
40f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.os.SystemClock;
41f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.util.AttributeSet;
42f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.view.Gravity;
43f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.view.RemotableViewMethod;
44f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.view.View;
45f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.view.ViewDebug;
46f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.view.accessibility.AccessibilityEvent;
47f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.view.accessibility.AccessibilityManager;
48f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.view.animation.AlphaAnimation;
49f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.view.animation.Animation;
50f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.view.animation.AnimationUtils;
51f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.view.animation.Interpolator;
52f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.view.animation.LinearInterpolator;
53f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.view.animation.Transformation;
54f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenimport android.widget.RemoteViews.RemoteView;
55f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
56f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
57f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen/**
58f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <p>
59f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * Visual indicator of progress in some operation.  Displays a bar to the user
60f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * representing how far the operation has progressed; the application can
61f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * change the amount of progress (modifying the length of the bar) as it moves
62f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * forward.  There is also a secondary progress displayable on a progress bar
63f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * which is useful for displaying intermediate progress, such as the buffer
64f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * level during a streaming playback progress bar.
65f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * </p>
66f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
67f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <p>
68f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * A progress bar can also be made indeterminate. In indeterminate mode, the
69f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * progress bar shows a cyclic animation without an indication of progress. This mode is used by
70f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * applications when the length of the task is unknown. The indeterminate progress bar can be either
71f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * a spinning wheel or a horizontal bar.
72f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * </p>
73f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
74f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <p>The following code example shows how a progress bar can be used from
75f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * a worker thread to update the user interface to notify the user of progress:
76f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * </p>
77f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
78f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <pre>
79f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * public class MyActivity extends Activity {
80f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *     private static final int PROGRESS = 0x1;
81f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
82f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *     private ProgressBar mProgress;
83f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *     private int mProgressStatus = 0;
84f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
85f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *     private Handler mHandler = new Handler();
86f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
87f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *     protected void onCreate(Bundle icicle) {
88f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *         super.onCreate(icicle);
89f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
90f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *         setContentView(R.layout.progressbar_activity);
91f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
92f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *         mProgress = (ProgressBar) findViewById(R.id.progress_bar);
93f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
94f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *         // Start lengthy operation in a background thread
95f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *         new Thread(new Runnable() {
96f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *             public void run() {
97f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *                 while (mProgressStatus &lt; 100) {
98f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *                     mProgressStatus = doWork();
99f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
100f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *                     // Update the progress bar
101f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *                     mHandler.post(new Runnable() {
102f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *                         public void run() {
103f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *                             mProgress.setProgress(mProgressStatus);
104f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *                         }
105f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *                     });
106f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *                 }
107f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *             }
108f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *         }).start();
109f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *     }
110f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * }</pre>
111f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
112f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <p>To add a progress bar to a layout file, you can use the {@code &lt;ProgressBar&gt;} element.
113f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * By default, the progress bar is a spinning wheel (an indeterminate indicator). To change to a
114f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * horizontal progress bar, apply the {@link android.R.style#Widget_ProgressBar_Horizontal
115f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * Widget.ProgressBar.Horizontal} style, like so:</p>
116f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
117f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <pre>
118f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * &lt;ProgressBar
119f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *     style="@android:style/Widget.ProgressBar.Horizontal"
120f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *     ... /&gt;</pre>
121f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
122f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <p>If you will use the progress bar to show real progress, you must use the horizontal bar. You
123f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * can then increment the  progress with {@link #incrementProgressBy incrementProgressBy()} or
124f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * {@link #setProgress setProgress()}. By default, the progress bar is full when it reaches 100. If
125f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * necessary, you can adjust the maximum value (the value for a full bar) using the {@link
126f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * android.R.styleable#ProgressBar_max android:max} attribute. Other attributes available are listed
127f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * below.</p>
128f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
129f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <p>Another common style to apply to the progress bar is {@link
130f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * android.R.style#Widget_ProgressBar_Small Widget.ProgressBar.Small}, which shows a smaller
131f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * version of the spinning wheel&mdash;useful when waiting for content to load.
132f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * For example, you can insert this kind of progress bar into your default layout for
133f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * a view that will be populated by some content fetched from the Internet&mdash;the spinning wheel
134f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * appears immediately and when your application receives the content, it replaces the progress bar
135f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * with the loaded content. For example:</p>
136f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
137f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <pre>
138f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * &lt;LinearLayout
139f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *     android:orientation="horizontal"
140f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *     ... &gt;
141f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *     &lt;ProgressBar
142f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *         android:layout_width="wrap_content"
143f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *         android:layout_height="wrap_content"
144f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *         style="@android:style/Widget.ProgressBar.Small"
145f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *         android:layout_marginRight="5dp" /&gt;
146f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *     &lt;TextView
147f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *         android:layout_width="wrap_content"
148f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *         android:layout_height="wrap_content"
149f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *         android:text="@string/loading" /&gt;
150f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * &lt;/LinearLayout&gt;</pre>
151f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
152f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <p>Other progress bar styles provided by the system include:</p>
153f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <ul>
154f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <li>{@link android.R.style#Widget_ProgressBar_Horizontal Widget.ProgressBar.Horizontal}</li>
155f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <li>{@link android.R.style#Widget_ProgressBar_Small Widget.ProgressBar.Small}</li>
156f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <li>{@link android.R.style#Widget_ProgressBar_Large Widget.ProgressBar.Large}</li>
157f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <li>{@link android.R.style#Widget_ProgressBar_Inverse Widget.ProgressBar.Inverse}</li>
158f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <li>{@link android.R.style#Widget_ProgressBar_Small_Inverse
159f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * Widget.ProgressBar.Small.Inverse}</li>
160f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <li>{@link android.R.style#Widget_ProgressBar_Large_Inverse
161f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * Widget.ProgressBar.Large.Inverse}</li>
162f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * </ul>
163f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <p>The "inverse" styles provide an inverse color scheme for the spinner, which may be necessary
164f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * if your application uses a light colored theme (a white background).</p>
165f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
166f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <p><strong>XML attributes</b></strong>
167f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * <p>
168f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * See {@link android.R.styleable#ProgressBar ProgressBar Attributes},
169f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * {@link android.R.styleable#View View Attributes}
170f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * </p>
171f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen *
172f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_animationResolution
173f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_indeterminate
174f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_indeterminateBehavior
175f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_indeterminateDrawable
176f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_indeterminateDuration
177f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_indeterminateOnly
178f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_interpolator
179f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_max
180f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_maxHeight
181f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_maxWidth
182f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_minHeight
183f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_minWidth
184f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_progress
185f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_progressDrawable
186f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen * @attr ref android.R.styleable#ProgressBar_secondaryProgress
187f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen */
188f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen@RemoteView
189f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissenpublic class ProgressBar extends View {
190f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private static final int MAX_LEVEL = 10000;
191f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private static final int ANIMATION_RESOLUTION = 200;
192f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private static final int TIMEOUT_SEND_ACCESSIBILITY_EVENT = 200;
193f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
194f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    int mMinWidth;
195f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    int mMaxWidth;
196f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    int mMinHeight;
197f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    int mMaxHeight;
198f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
199f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private int mProgress;
200f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private int mSecondaryProgress;
201f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private int mMax;
202f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
203f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private int mBehavior;
204f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private int mDuration;
205f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private boolean mIndeterminate;
206f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private boolean mOnlyIndeterminate;
207f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private Transformation mTransformation;
208f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private AlphaAnimation mAnimation;
209f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private Drawable mIndeterminateDrawable;
210f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private Drawable mProgressDrawable;
211f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private Drawable mCurrentDrawable;
212f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    Bitmap mSampleTile;
213f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private boolean mNoInvalidate;
214f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private Interpolator mInterpolator;
215f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private RefreshProgressRunnable mRefreshProgressRunnable;
216f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private long mUiThreadId;
217f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private boolean mShouldStartAnimationDrawable;
218f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private long mLastDrawTime;
219f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
220f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private boolean mInDrawing;
221f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
222f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private int mAnimationResolution;
223f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
224f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private AccessibilityEventSender mAccessibilityEventSender;
225f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
226f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
227f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * Create a new progress bar with range 0...100 and initial progress of 0.
228f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @param context the application environment
229f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
230f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public ProgressBar(Context context) {
231f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        this(context, null);
232f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
233f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
234f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public ProgressBar(Context context, AttributeSet attrs) {
235f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        this(context, attrs, com.android.internal.R.attr.progressBarStyle);
236f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
237f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
238f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public ProgressBar(Context context, AttributeSet attrs, int defStyle) {
239f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        this(context, attrs, defStyle, 0);
240f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
241f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
242f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
243f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @hide
244f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
245f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public ProgressBar(Context context, AttributeSet attrs, int defStyle, int styleRes) {
246f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        super(context, attrs, defStyle);
247f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mUiThreadId = Thread.currentThread().getId();
248f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        initProgressBar();
249f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
250f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        TypedArray a =
251f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            context.obtainStyledAttributes(attrs, R.styleable.ProgressBar, defStyle, styleRes);
252f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
253f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mNoInvalidate = true;
254f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
255f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        Drawable drawable = a.getDrawable(R.styleable.ProgressBar_progressDrawable);
256f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (drawable != null) {
257f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            drawable = tileify(drawable, false);
258f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            // Calling this method can set mMaxHeight, make sure the corresponding
259f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            // XML attribute for mMaxHeight is read after calling this method
260f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            setProgressDrawable(drawable);
261f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
262f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
263f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
264f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mDuration = a.getInt(R.styleable.ProgressBar_indeterminateDuration, mDuration);
265f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
266f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mMinWidth = a.getDimensionPixelSize(R.styleable.ProgressBar_minWidth, mMinWidth);
267f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mMaxWidth = a.getDimensionPixelSize(R.styleable.ProgressBar_maxWidth, mMaxWidth);
268f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mMinHeight = a.getDimensionPixelSize(R.styleable.ProgressBar_minHeight, mMinHeight);
269f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mMaxHeight = a.getDimensionPixelSize(R.styleable.ProgressBar_maxHeight, mMaxHeight);
270f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
271f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mBehavior = a.getInt(R.styleable.ProgressBar_indeterminateBehavior, mBehavior);
272f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
273f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        final int resID = a.getResourceId(
274f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                com.android.internal.R.styleable.ProgressBar_interpolator,
275f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                android.R.anim.linear_interpolator); // default to linear interpolator
276f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (resID > 0) {
277f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            setInterpolator(context, resID);
278f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
279f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
280f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        setMax(a.getInt(R.styleable.ProgressBar_max, mMax));
281f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
282f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        setProgress(a.getInt(R.styleable.ProgressBar_progress, mProgress));
283f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
284f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        setSecondaryProgress(
285f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                a.getInt(R.styleable.ProgressBar_secondaryProgress, mSecondaryProgress));
286f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
287f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        drawable = a.getDrawable(R.styleable.ProgressBar_indeterminateDrawable);
288f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (drawable != null) {
289f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            drawable = tileifyIndeterminate(drawable);
290f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            setIndeterminateDrawable(drawable);
291f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
292f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
293f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mOnlyIndeterminate = a.getBoolean(
294f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                R.styleable.ProgressBar_indeterminateOnly, mOnlyIndeterminate);
295f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
296f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mNoInvalidate = false;
297f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
298f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        setIndeterminate(mOnlyIndeterminate || a.getBoolean(
299f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                R.styleable.ProgressBar_indeterminate, mIndeterminate));
300f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
301f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mAnimationResolution = a.getInteger(R.styleable.ProgressBar_animationResolution,
302f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                ANIMATION_RESOLUTION);
303f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
304f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        a.recycle();
305f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
306f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
307f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
308f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * Converts a drawable to a tiled version of itself. It will recursively
309f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * traverse layer and state list drawables.
310f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
311f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private Drawable tileify(Drawable drawable, boolean clip) {
312f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
313f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (drawable instanceof LayerDrawable) {
314f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            LayerDrawable background = (LayerDrawable) drawable;
315f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            final int N = background.getNumberOfLayers();
316f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            Drawable[] outDrawables = new Drawable[N];
317f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
318f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            for (int i = 0; i < N; i++) {
319f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                int id = background.getId(i);
320f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                outDrawables[i] = tileify(background.getDrawable(i),
321f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                        (id == R.id.progress || id == R.id.secondaryProgress));
322f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
323f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
324f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            LayerDrawable newBg = new LayerDrawable(outDrawables);
325f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
326f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            for (int i = 0; i < N; i++) {
327f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                newBg.setId(i, background.getId(i));
328f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
329f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
330f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            return newBg;
331f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
332f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        } else if (drawable instanceof StateListDrawable) {
333f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            StateListDrawable in = (StateListDrawable) drawable;
334f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            StateListDrawable out = new StateListDrawable();
335f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            int numStates = in.getStateCount();
336f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            for (int i = 0; i < numStates; i++) {
337f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                out.addState(in.getStateSet(i), tileify(in.getStateDrawable(i), clip));
338f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
339f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            return out;
340f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
341f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        } else if (drawable instanceof BitmapDrawable) {
342f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap();
343f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            if (mSampleTile == null) {
344f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                mSampleTile = tileBitmap;
345f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
346f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
347f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
348f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
349f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
350f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                    Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
351f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            shapeDrawable.getPaint().setShader(bitmapShader);
352f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
353f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
354f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                    ClipDrawable.HORIZONTAL) : shapeDrawable;
355f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
356f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
357f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        return drawable;
358f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
359f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
360f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    Shape getDrawableShape() {
361f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        final float[] roundedCorners = new float[] { 5, 5, 5, 5, 5, 5, 5, 5 };
362f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        return new RoundRectShape(roundedCorners, null, null);
363f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
364f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
365f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
366f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * Convert a AnimationDrawable for use as a barberpole animation.
367f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * Each frame of the animation is wrapped in a ClipDrawable and
368f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * given a tiling BitmapShader.
369f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
370f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private Drawable tileifyIndeterminate(Drawable drawable) {
371f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (drawable instanceof AnimationDrawable) {
372f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            AnimationDrawable background = (AnimationDrawable) drawable;
373f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            final int N = background.getNumberOfFrames();
374f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            AnimationDrawable newBg = new AnimationDrawable();
375f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            newBg.setOneShot(background.isOneShot());
376f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
377f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            for (int i = 0; i < N; i++) {
378f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                Drawable frame = tileify(background.getFrame(i), true);
379f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                frame.setLevel(10000);
380f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                newBg.addFrame(frame, background.getDuration(i));
381f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
382f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            newBg.setLevel(10000);
383f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            drawable = newBg;
384f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
385f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        return drawable;
386f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
387f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
388f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
389f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>
390f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * Initialize the progress bar's default values:
391f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * </p>
392f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <ul>
393f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <li>progress = 0</li>
394f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <li>max = 100</li>
395f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <li>animation duration = 4000 ms</li>
396f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <li>indeterminate = false</li>
397f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <li>behavior = repeat</li>
398f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * </ul>
399f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
400f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private void initProgressBar() {
401f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mMax = 100;
402f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mProgress = 0;
403f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mSecondaryProgress = 0;
404f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mIndeterminate = false;
405f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mOnlyIndeterminate = false;
406f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mDuration = 4000;
407f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mBehavior = AlphaAnimation.RESTART;
408f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mMinWidth = 24;
409f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mMaxWidth = 48;
410f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mMinHeight = 24;
411f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mMaxHeight = 48;
412f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
413f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
414f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
415f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Indicate whether this progress bar is in indeterminate mode.</p>
416f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
417f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @return true if the progress bar is in indeterminate mode
418f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
419f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @ViewDebug.ExportedProperty(category = "progress")
420f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public synchronized boolean isIndeterminate() {
421f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        return mIndeterminate;
422f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
423f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
424f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
425f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Change the indeterminate mode for this progress bar. In indeterminate
426f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * mode, the progress is ignored and the progress bar shows an infinite
427f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * animation instead.</p>
428f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
429f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * If this progress bar's style only supports indeterminate mode (such as the circular
430f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * progress bars), then this will be ignored.
431f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
432f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @param indeterminate true to enable the indeterminate mode
433f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
434f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @android.view.RemotableViewMethod
435f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public synchronized void setIndeterminate(boolean indeterminate) {
436f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if ((!mOnlyIndeterminate || !mIndeterminate) && indeterminate != mIndeterminate) {
437f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mIndeterminate = indeterminate;
438f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
439f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            if (indeterminate) {
440f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                // swap between indeterminate and regular backgrounds
441f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                mCurrentDrawable = mIndeterminateDrawable;
442f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                startAnimation();
443f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            } else {
444f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                mCurrentDrawable = mProgressDrawable;
445f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                stopAnimation();
446f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
447f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
448f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
449f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
450f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
451f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Get the drawable used to draw the progress bar in
452f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * indeterminate mode.</p>
453f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
454f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @return a {@link android.graphics.drawable.Drawable} instance
455f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
456f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setIndeterminateDrawable(android.graphics.drawable.Drawable)
457f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setIndeterminate(boolean)
458f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
459f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public Drawable getIndeterminateDrawable() {
460f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        return mIndeterminateDrawable;
461f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
462f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
463f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
464f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Define the drawable used to draw the progress bar in
465f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * indeterminate mode.</p>
466f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
467f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @param d the new drawable
468f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
469f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #getIndeterminateDrawable()
470f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setIndeterminate(boolean)
471f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
472f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public void setIndeterminateDrawable(Drawable d) {
473f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (d != null) {
474f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            d.setCallback(this);
475f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
476f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mIndeterminateDrawable = d;
477f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mIndeterminate) {
478f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mCurrentDrawable = d;
479f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            postInvalidate();
480f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
481f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
482f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
483f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
484f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Get the drawable used to draw the progress bar in
485f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * progress mode.</p>
486f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
487f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @return a {@link android.graphics.drawable.Drawable} instance
488f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
489f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setProgressDrawable(android.graphics.drawable.Drawable)
490f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setIndeterminate(boolean)
491f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
492f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public Drawable getProgressDrawable() {
493f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        return mProgressDrawable;
494f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
495f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
496f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
497f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Define the drawable used to draw the progress bar in
498f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * progress mode.</p>
499f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
500f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @param d the new drawable
501f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
502f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #getProgressDrawable()
503f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setIndeterminate(boolean)
504f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
505f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public void setProgressDrawable(Drawable d) {
506f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        boolean needUpdate;
507f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mProgressDrawable != null && d != mProgressDrawable) {
508f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mProgressDrawable.setCallback(null);
509f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            needUpdate = true;
510f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        } else {
511f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            needUpdate = false;
512f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
513f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
514f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (d != null) {
515f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            d.setCallback(this);
516f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
517f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            // Make sure the ProgressBar is always tall enough
518f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            int drawableHeight = d.getMinimumHeight();
519f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            if (mMaxHeight < drawableHeight) {
520f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                mMaxHeight = drawableHeight;
521f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                requestLayout();
522f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
523f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
524f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mProgressDrawable = d;
525f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (!mIndeterminate) {
526f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mCurrentDrawable = d;
527f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            postInvalidate();
528f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
529f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
530f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (needUpdate) {
531f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            updateDrawableBounds(getWidth(), getHeight());
532f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            updateDrawableState();
533f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            doRefreshProgress(R.id.progress, mProgress, false, false);
534f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            doRefreshProgress(R.id.secondaryProgress, mSecondaryProgress, false, false);
535f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
536f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
537f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
538f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
539f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @return The drawable currently used to draw the progress bar
540f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
541f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    Drawable getCurrentDrawable() {
542f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        return mCurrentDrawable;
543f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
544f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
545f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
546f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    protected boolean verifyDrawable(Drawable who) {
547f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        return who == mProgressDrawable || who == mIndeterminateDrawable
548f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                || super.verifyDrawable(who);
549f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
550f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
551f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
552f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public void jumpDrawablesToCurrentState() {
553f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        super.jumpDrawablesToCurrentState();
554f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mProgressDrawable != null) mProgressDrawable.jumpToCurrentState();
555f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mIndeterminateDrawable != null) mIndeterminateDrawable.jumpToCurrentState();
556f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
557f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
558f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
559f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public void postInvalidate() {
560f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (!mNoInvalidate) {
561f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            super.postInvalidate();
562f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
563f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
564f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
565f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private class RefreshProgressRunnable implements Runnable {
566f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
567f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        private int mId;
568f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        private int mProgress;
569f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        private boolean mFromUser;
570f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
571f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        RefreshProgressRunnable(int id, int progress, boolean fromUser) {
572f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mId = id;
573f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mProgress = progress;
574f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mFromUser = fromUser;
575f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
576f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
577f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        public void run() {
578f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            doRefreshProgress(mId, mProgress, mFromUser, true);
579f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            // Put ourselves back in the cache when we are done
580f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mRefreshProgressRunnable = this;
581f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
582f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
583f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        public void setup(int id, int progress, boolean fromUser) {
584f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mId = id;
585f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mProgress = progress;
586f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mFromUser = fromUser;
587f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
588f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
589f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
590f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
591f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private synchronized void doRefreshProgress(int id, int progress, boolean fromUser,
592f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            boolean callBackToApp) {
593f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        float scale = mMax > 0 ? (float) progress / (float) mMax : 0;
594f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        final Drawable d = mCurrentDrawable;
595f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (d != null) {
596f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            Drawable progressDrawable = null;
597f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
598f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            if (d instanceof LayerDrawable) {
599f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                progressDrawable = ((LayerDrawable) d).findDrawableByLayerId(id);
600f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
601f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
602f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            final int level = (int) (scale * MAX_LEVEL);
603f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            (progressDrawable != null ? progressDrawable : d).setLevel(level);
604f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        } else {
605f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            invalidate();
606f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
607f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
608f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (callBackToApp && id == R.id.progress) {
609f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            onProgressRefresh(scale, fromUser);
610f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
611f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
612f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
613f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    void onProgressRefresh(float scale, boolean fromUser) {
614f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
615f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            scheduleAccessibilityEventSender();
616f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
617f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
618f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
619f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private synchronized void refreshProgress(int id, int progress, boolean fromUser) {
620f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mUiThreadId == Thread.currentThread().getId()) {
621f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            doRefreshProgress(id, progress, fromUser, true);
622f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        } else {
623f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            RefreshProgressRunnable r;
624f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            if (mRefreshProgressRunnable != null) {
625f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                // Use cached RefreshProgressRunnable if available
626f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                r = mRefreshProgressRunnable;
627f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                // Uncache it
628f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                mRefreshProgressRunnable = null;
629f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                r.setup(id, progress, fromUser);
630f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            } else {
631f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                // Make a new one
632f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                r = new RefreshProgressRunnable(id, progress, fromUser);
633f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
634f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            post(r);
635f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
636f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
637f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
638f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
639f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Set the current progress to the specified value. Does not do anything
640f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * if the progress bar is in indeterminate mode.</p>
641f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
642f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @param progress the new progress, between 0 and {@link #getMax()}
643f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
644f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setIndeterminate(boolean)
645f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #isIndeterminate()
646f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #getProgress()
647f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #incrementProgressBy(int)
648f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
649f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @android.view.RemotableViewMethod
650f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public synchronized void setProgress(int progress) {
651f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        setProgress(progress, false);
652f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
653f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
654f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @android.view.RemotableViewMethod
655f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    synchronized void setProgress(int progress, boolean fromUser) {
656f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mIndeterminate) {
657f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            return;
658f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
659f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
660f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (progress < 0) {
661f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            progress = 0;
662f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
663f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
664f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (progress > mMax) {
665f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            progress = mMax;
666f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
667f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
668f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (progress != mProgress) {
669f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mProgress = progress;
670f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            refreshProgress(R.id.progress, mProgress, fromUser);
671f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
672f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
673f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
674f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
675f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>
676f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * Set the current secondary progress to the specified value. Does not do
677f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * anything if the progress bar is in indeterminate mode.
678f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * </p>
679f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
680f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @param secondaryProgress the new secondary progress, between 0 and {@link #getMax()}
681f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setIndeterminate(boolean)
682f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #isIndeterminate()
683f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #getSecondaryProgress()
684f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #incrementSecondaryProgressBy(int)
685f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
686f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @android.view.RemotableViewMethod
687f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public synchronized void setSecondaryProgress(int secondaryProgress) {
688f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mIndeterminate) {
689f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            return;
690f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
691f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
692f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (secondaryProgress < 0) {
693f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            secondaryProgress = 0;
694f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
695f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
696f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (secondaryProgress > mMax) {
697f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            secondaryProgress = mMax;
698f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
699f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
700f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (secondaryProgress != mSecondaryProgress) {
701f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mSecondaryProgress = secondaryProgress;
702f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            refreshProgress(R.id.secondaryProgress, mSecondaryProgress, false);
703f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
704f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
705f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
706f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
707f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Get the progress bar's current level of progress. Return 0 when the
708f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * progress bar is in indeterminate mode.</p>
709f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
710f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @return the current progress, between 0 and {@link #getMax()}
711f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
712f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setIndeterminate(boolean)
713f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #isIndeterminate()
714f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setProgress(int)
715f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setMax(int)
716f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #getMax()
717f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
718f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @ViewDebug.ExportedProperty(category = "progress")
719f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public synchronized int getProgress() {
720f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        return mIndeterminate ? 0 : mProgress;
721f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
722f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
723f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
724f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Get the progress bar's current level of secondary progress. Return 0 when the
725f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * progress bar is in indeterminate mode.</p>
726f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
727f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @return the current secondary progress, between 0 and {@link #getMax()}
728f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
729f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setIndeterminate(boolean)
730f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #isIndeterminate()
731f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setSecondaryProgress(int)
732f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setMax(int)
733f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #getMax()
734f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
735f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @ViewDebug.ExportedProperty(category = "progress")
736f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public synchronized int getSecondaryProgress() {
737f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        return mIndeterminate ? 0 : mSecondaryProgress;
738f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
739f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
740f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
741f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Return the upper limit of this progress bar's range.</p>
742f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
743f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @return a positive integer
744f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
745f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setMax(int)
746f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #getProgress()
747f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #getSecondaryProgress()
748f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
749f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @ViewDebug.ExportedProperty(category = "progress")
750f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public synchronized int getMax() {
751f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        return mMax;
752f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
753f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
754f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
755f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Set the range of the progress bar to 0...<tt>max</tt>.</p>
756f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
757f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @param max the upper range of this progress bar
758f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
759f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #getMax()
760f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setProgress(int)
761f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setSecondaryProgress(int)
762f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
763f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @android.view.RemotableViewMethod
764f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public synchronized void setMax(int max) {
765f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (max < 0) {
766f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            max = 0;
767f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
768f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (max != mMax) {
769f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mMax = max;
770f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            postInvalidate();
771f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
772f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            if (mProgress > max) {
773f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                mProgress = max;
774f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
775f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            refreshProgress(R.id.progress, mProgress, false);
776f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
777f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
778f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
779f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
780f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Increase the progress bar's progress by the specified amount.</p>
781f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
782f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @param diff the amount by which the progress must be increased
783f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
784f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setProgress(int)
785f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
786f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public synchronized final void incrementProgressBy(int diff) {
787f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        setProgress(mProgress + diff);
788f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
789f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
790f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
791f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Increase the progress bar's secondary progress by the specified amount.</p>
792f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
793f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @param diff the amount by which the secondary progress must be increased
794f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
795f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @see #setSecondaryProgress(int)
796f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
797f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public synchronized final void incrementSecondaryProgressBy(int diff) {
798f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        setSecondaryProgress(mSecondaryProgress + diff);
799f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
800f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
801f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
802f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Start the indeterminate progress animation.</p>
803f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
804f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    void startAnimation() {
805f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (getVisibility() != VISIBLE) {
806f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            return;
807f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
808f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
809f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mIndeterminateDrawable instanceof Animatable) {
810f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mShouldStartAnimationDrawable = true;
811f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mAnimation = null;
812f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        } else {
813f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            if (mInterpolator == null) {
814f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                mInterpolator = new LinearInterpolator();
815f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
816f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
817f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mTransformation = new Transformation();
818f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mAnimation = new AlphaAnimation(0.0f, 1.0f);
819f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mAnimation.setRepeatMode(mBehavior);
820f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mAnimation.setRepeatCount(Animation.INFINITE);
821f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mAnimation.setDuration(mDuration);
822f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mAnimation.setInterpolator(mInterpolator);
823f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mAnimation.setStartTime(Animation.START_ON_FIRST_FRAME);
824f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
825f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        postInvalidate();
826f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
827f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
828f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
829f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * <p>Stop the indeterminate progress animation.</p>
830f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
831f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    void stopAnimation() {
832f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mAnimation = null;
833f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mTransformation = null;
834f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mIndeterminateDrawable instanceof Animatable) {
835f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            ((Animatable) mIndeterminateDrawable).stop();
836f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mShouldStartAnimationDrawable = false;
837f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
838f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        postInvalidate();
839f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
840f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
841f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
842f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * Sets the acceleration curve for the indeterminate animation.
843f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * The interpolator is loaded as a resource from the specified context.
844f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
845f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @param context The application environment
846f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @param resID The resource identifier of the interpolator to load
847f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
848f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public void setInterpolator(Context context, int resID) {
849f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        setInterpolator(AnimationUtils.loadInterpolator(context, resID));
850f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
851f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
852f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
853f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * Sets the acceleration curve for the indeterminate animation.
854f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * Defaults to a linear interpolation.
855f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
856f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @param interpolator The interpolator which defines the acceleration curve
857f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
858f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public void setInterpolator(Interpolator interpolator) {
859f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        mInterpolator = interpolator;
860f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
861f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
862f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
863f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * Gets the acceleration curve type for the indeterminate animation.
864f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *
865f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * @return the {@link Interpolator} associated to this animation
866f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
867f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public Interpolator getInterpolator() {
868f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        return mInterpolator;
869f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
870f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
871f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
872f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @RemotableViewMethod
873f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public void setVisibility(int v) {
874f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (getVisibility() != v) {
875f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            super.setVisibility(v);
876f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
877f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            if (mIndeterminate) {
878f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                // let's be nice with the UI thread
879f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                if (v == GONE || v == INVISIBLE) {
880f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                    stopAnimation();
881f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                } else {
882f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                    startAnimation();
883f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                }
884f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
885f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
886f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
887f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
888f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
889f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    protected void onVisibilityChanged(View changedView, int visibility) {
890f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        super.onVisibilityChanged(changedView, visibility);
891f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
892f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mIndeterminate) {
893f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            // let's be nice with the UI thread
894f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            if (visibility == GONE || visibility == INVISIBLE) {
895f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                stopAnimation();
896f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            } else {
897f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                startAnimation();
898f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
899f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
900f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
901f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
902f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
903f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public void invalidateDrawable(Drawable dr) {
904f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (!mInDrawing) {
905f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            if (verifyDrawable(dr)) {
906f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                final Rect dirty = dr.getBounds();
907f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                final int scrollX = mScrollX + mPaddingLeft;
908f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                final int scrollY = mScrollY + mPaddingTop;
909f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
910f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                invalidate(dirty.left + scrollX, dirty.top + scrollY,
911f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                        dirty.right + scrollX, dirty.bottom + scrollY);
912f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            } else {
913f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                super.invalidateDrawable(dr);
914f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
915f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
916f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
917f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
918f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
919f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
920f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        updateDrawableBounds(w, h);
921f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
922f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
923f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private void updateDrawableBounds(int w, int h) {
924f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        // onDraw will translate the canvas so we draw starting at 0,0
925f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        int right = w - mPaddingRight - mPaddingLeft;
926f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        int bottom = h - mPaddingBottom - mPaddingTop;
9270962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen        int top = 0;
9280962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen        int left = 0;
929f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
930f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mIndeterminateDrawable != null) {
9310962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen            // Aspect ratio logic does not apply to AnimationDrawables
9320962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen            if (mOnlyIndeterminate && !(mIndeterminateDrawable instanceof AnimationDrawable)) {
9330962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                // Maintain aspect ratio. Certain kinds of animated drawables
9340962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                // get very confused otherwise.
9350962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                final int intrinsicWidth = mIndeterminateDrawable.getIntrinsicWidth();
9360962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                final int intrinsicHeight = mIndeterminateDrawable.getIntrinsicHeight();
9370962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                final float intrinsicAspect = (float) intrinsicWidth / intrinsicHeight;
9380962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                final float boundAspect = (float) w / h;
9390962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                if (intrinsicAspect != boundAspect) {
9400962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                    if (boundAspect > intrinsicAspect) {
9410962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                        // New width is larger. Make it smaller to match height.
9420962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                        final int width = (int) (h * intrinsicAspect);
9430962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                        left = (w - width) / 2;
9440962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                        right = left + width;
9450962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                    } else {
9460962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                        // New height is larger. Make it smaller to match width.
9470962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                        final int height = (int) (w * (1 / intrinsicAspect));
9480962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                        top = (h - height) / 2;
9490962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                        bottom = top + height;
9500962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                    }
9510962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen                }
9520962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen            }
9530962a4b159ae5d4ea427c9e6fc32ff3722cbc16cMarco Nelissen            mIndeterminateDrawable.setBounds(left, top, right, bottom);
954f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
955f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
956f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mProgressDrawable != null) {
957f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mProgressDrawable.setBounds(0, 0, right, bottom);
958f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
959f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
960f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
961f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
962f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    protected synchronized void onDraw(Canvas canvas) {
963f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        super.onDraw(canvas);
964f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
965f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        Drawable d = mCurrentDrawable;
966f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (d != null) {
967f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            // Translate canvas so a indeterminate circular progress bar with padding
968f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            // rotates properly in its animation
969f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            canvas.save();
970f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            canvas.translate(mPaddingLeft, mPaddingTop);
971f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            long time = getDrawingTime();
972f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            if (mAnimation != null) {
973f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                mAnimation.getTransformation(time, mTransformation);
974f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                float scale = mTransformation.getAlpha();
975f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                try {
976f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                    mInDrawing = true;
977f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                    d.setLevel((int) (scale * MAX_LEVEL));
978f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                } finally {
979f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                    mInDrawing = false;
980f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                }
981f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                if (SystemClock.uptimeMillis() - mLastDrawTime >= mAnimationResolution) {
982f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                    mLastDrawTime = SystemClock.uptimeMillis();
983f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                    postInvalidateDelayed(mAnimationResolution);
984f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                }
985f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
986f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            d.draw(canvas);
987f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            canvas.restore();
988f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            if (mShouldStartAnimationDrawable && d instanceof Animatable) {
989f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                ((Animatable) d).start();
990f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                mShouldStartAnimationDrawable = false;
991f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
992f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
993f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
994f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
995f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
996f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
997f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        Drawable d = mCurrentDrawable;
998f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
999f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        int dw = 0;
1000f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        int dh = 0;
1001f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (d != null) {
1002f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            dw = Math.max(mMinWidth, Math.min(mMaxWidth, d.getIntrinsicWidth()));
1003f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            dh = Math.max(mMinHeight, Math.min(mMaxHeight, d.getIntrinsicHeight()));
1004f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
1005f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        updateDrawableState();
1006f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        dw += mPaddingLeft + mPaddingRight;
1007f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        dh += mPaddingTop + mPaddingBottom;
1008f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1009f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        setMeasuredDimension(resolveSizeAndState(dw, widthMeasureSpec, 0),
1010f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                resolveSizeAndState(dh, heightMeasureSpec, 0));
1011f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
1012f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1013f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
1014f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    protected void drawableStateChanged() {
1015f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        super.drawableStateChanged();
1016f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        updateDrawableState();
1017f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
1018f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1019f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private void updateDrawableState() {
1020f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        int[] state = getDrawableState();
1021f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1022f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mProgressDrawable != null && mProgressDrawable.isStateful()) {
1023f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mProgressDrawable.setState(state);
1024f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
1025f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1026f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mIndeterminateDrawable != null && mIndeterminateDrawable.isStateful()) {
1027f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mIndeterminateDrawable.setState(state);
1028f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
1029f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
1030f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1031f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    static class SavedState extends BaseSavedState {
1032f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        int progress;
1033f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        int secondaryProgress;
1034f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1035f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        /**
1036f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen         * Constructor called from {@link ProgressBar#onSaveInstanceState()}
1037f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen         */
1038f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        SavedState(Parcelable superState) {
1039f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            super(superState);
1040f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
1041f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1042f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        /**
1043f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen         * Constructor called from {@link #CREATOR}
1044f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen         */
1045f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        private SavedState(Parcel in) {
1046f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            super(in);
1047f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            progress = in.readInt();
1048f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            secondaryProgress = in.readInt();
1049f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
1050f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1051f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        @Override
1052f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        public void writeToParcel(Parcel out, int flags) {
1053f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            super.writeToParcel(out, flags);
1054f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            out.writeInt(progress);
1055f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            out.writeInt(secondaryProgress);
1056f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
1057f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1058f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        public static final Parcelable.Creator<SavedState> CREATOR
1059f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                = new Parcelable.Creator<SavedState>() {
1060f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            public SavedState createFromParcel(Parcel in) {
1061f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                return new SavedState(in);
1062f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
1063f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1064f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            public SavedState[] newArray(int size) {
1065f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen                return new SavedState[size];
1066f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            }
1067f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        };
1068f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
1069f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1070f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
1071f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public Parcelable onSaveInstanceState() {
1072f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        // Force our ancestor class to save its state
1073f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        Parcelable superState = super.onSaveInstanceState();
1074f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        SavedState ss = new SavedState(superState);
1075f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1076f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        ss.progress = mProgress;
1077f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        ss.secondaryProgress = mSecondaryProgress;
1078f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1079f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        return ss;
1080f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
1081f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1082f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
1083f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public void onRestoreInstanceState(Parcelable state) {
1084f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        SavedState ss = (SavedState) state;
1085f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        super.onRestoreInstanceState(ss.getSuperState());
1086f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1087f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        setProgress(ss.progress);
1088f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        setSecondaryProgress(ss.secondaryProgress);
1089f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
1090f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1091f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
1092f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    protected void onAttachedToWindow() {
1093f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        super.onAttachedToWindow();
1094f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mIndeterminate) {
1095f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            startAnimation();
1096f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
1097f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
1098f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1099f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
1100f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    protected void onDetachedFromWindow() {
1101f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mIndeterminate) {
1102f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            stopAnimation();
1103f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
1104f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if(mRefreshProgressRunnable != null) {
1105f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            removeCallbacks(mRefreshProgressRunnable);
1106f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
1107f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mAccessibilityEventSender != null) {
1108f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            removeCallbacks(mAccessibilityEventSender);
1109f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
1110f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        // This should come after stopAnimation(), otherwise an invalidate message remains in the
1111f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        // queue, which can prevent the entire view hierarchy from being GC'ed during a rotation
1112f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        super.onDetachedFromWindow();
1113f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
1114f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1115f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    @Override
1116f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
1117f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        super.onInitializeAccessibilityEvent(event);
1118f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        event.setItemCount(mMax);
1119f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        event.setCurrentItemIndex(mProgress);
1120f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
1121f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1122f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
1123f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * Schedule a command for sending an accessibility event.
1124f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * </br>
1125f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * Note: A command is used to ensure that accessibility events
1126f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *       are sent at most one in a given time frame to save
1127f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     *       system resources while the progress changes quickly.
1128f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
1129f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private void scheduleAccessibilityEventSender() {
1130f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        if (mAccessibilityEventSender == null) {
1131f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            mAccessibilityEventSender = new AccessibilityEventSender();
1132f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        } else {
1133f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            removeCallbacks(mAccessibilityEventSender);
1134f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
1135f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        postDelayed(mAccessibilityEventSender, TIMEOUT_SEND_ACCESSIBILITY_EVENT);
1136f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
1137f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen
1138f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    /**
1139f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     * Command for sending an accessibility event.
1140f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen     */
1141f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    private class AccessibilityEventSender implements Runnable {
1142f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        public void run() {
1143f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
1144f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen        }
1145f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen    }
1146f568b605f08a5d8401e21387bf9c4a83167d1160Marco Nelissen}
1147