blob: 8113b40eaee098c54139f2d21c5d295742fcbf46 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.widget;
18
Alan Viverettea64ed3b2015-09-23 10:01:45 -040019import android.animation.ObjectAnimator;
Adam Powellc1bba9b2016-03-03 16:51:17 -080020import android.annotation.InterpolatorRes;
Siva Velusamy94a6d152015-05-05 15:07:00 -070021import android.annotation.NonNull;
Alan Viverette91174362014-06-17 14:51:45 -070022import android.annotation.Nullable;
Mihai Popacbc059d2019-02-05 18:35:29 +000023import android.annotation.Px;
Mathew Inwood978c6e22018-08-21 15:58:55 +010024import android.annotation.UnsupportedAppUsage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.content.Context;
Alan Viverette91174362014-06-17 14:51:45 -070026import android.content.res.ColorStateList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.content.res.TypedArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.graphics.Canvas;
Adam Powellc1bba9b2016-03-03 16:51:17 -080029import android.graphics.PorterDuff;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.graphics.Rect;
Steve Howardb25ffff2010-08-20 17:39:26 -070031import android.graphics.Shader;
32import android.graphics.drawable.Animatable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.graphics.drawable.AnimationDrawable;
34import android.graphics.drawable.BitmapDrawable;
35import android.graphics.drawable.ClipDrawable;
36import android.graphics.drawable.Drawable;
37import android.graphics.drawable.LayerDrawable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.graphics.drawable.StateListDrawable;
39import android.graphics.drawable.shapes.RoundRectShape;
40import android.graphics.drawable.shapes.Shape;
Adam Powell84113362019-02-05 13:32:47 -080041import android.os.Build;
Steve Howardb25ffff2010-08-20 17:39:26 -070042import android.os.Parcel;
43import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.util.AttributeSet;
Adam Powellc1bba9b2016-03-03 16:51:17 -080045import android.util.FloatProperty;
Alan Viverette12a44912015-04-16 13:06:00 -070046import android.util.MathUtils;
Svetoslav Ganovabae2a12012-11-27 16:59:37 -080047import android.util.Pools.SynchronizedPool;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.view.Gravity;
Steve Howardb25ffff2010-08-20 17:39:26 -070049import android.view.RemotableViewMethod;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.view.View;
Steve Zeigler7a367882010-02-23 16:39:08 -080051import android.view.ViewDebug;
Siva Velusamy94a6d152015-05-05 15:07:00 -070052import android.view.ViewHierarchyEncoder;
Svetoslav Ganov6518ad72011-03-18 16:19:55 -070053import android.view.accessibility.AccessibilityEvent;
54import android.view.accessibility.AccessibilityManager;
Adam Powellc1bba9b2016-03-03 16:51:17 -080055import android.view.accessibility.AccessibilityNodeInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056import android.view.animation.AlphaAnimation;
57import android.view.animation.Animation;
58import android.view.animation.AnimationUtils;
Alan Viverettea64ed3b2015-09-23 10:01:45 -040059import android.view.animation.DecelerateInterpolator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.view.animation.Interpolator;
61import android.view.animation.LinearInterpolator;
62import android.view.animation.Transformation;
Ashley Rose55f9f922019-01-28 19:29:36 -050063import android.view.inspector.InspectableProperty;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.widget.RemoteViews.RemoteView;
Aurimas Liutikas99441c52016-10-11 16:48:32 -070065
Adam Powellc1bba9b2016-03-03 16:51:17 -080066import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067
Adam Powella0506632012-04-10 17:19:20 -070068import java.util.ArrayList;
69
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070/**
71 * <p>
Joe Fernandez72a9d592017-04-25 22:58:34 -070072 * A user interface element that indicates the progress of an operation.
73 * Progress bar supports two modes to represent progress: determinate, and indeterminate. For
74 * a visual overview of the difference between determinate and indeterminate progress modes, see
75 * <a href="https://material.io/guidelines/components/progress-activity.html#progress-activity-types-of-indicators">
76 * Progress & activity</a>.
77 * Display progress bars to a user in a non-interruptive way.
78 * Show the progress bar in your app's user interface or in a notification
79 * instead of within a dialog.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 * </p>
Joe Fernandez72a9d592017-04-25 22:58:34 -070081 * <h3>Indeterminate Progress</h3>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 * <p>
Joe Fernandez72a9d592017-04-25 22:58:34 -070083 * Use indeterminate mode for the progress bar when you do not know how long an
84 * operation will take.
85 * Indeterminate mode is the default for progress bar and shows a cyclic animation without a
86 * specific amount of progress indicated.
87 * The following example shows an indeterminate progress bar:
Scott Main42f139c2011-04-29 10:31:10 -070088 * <pre>
89 * &lt;ProgressBar
Joe Fernandez72a9d592017-04-25 22:58:34 -070090 * android:id="@+id/indeterminateBar"
91 * android:layout_width="wrap_content"
92 * android:layout_height="wrap_content"
93 * /&gt;
94 * </pre>
95 * </p>
96 * <h3>Determinate Progress</h3>
97 * <p>
98 * Use determinate mode for the progress bar when you want to show that a specific quantity of
99 * progress has occurred.
100 * For example, the percent remaining of a file being retrieved, the amount records in
101 * a batch written to database, or the percent remaining of an audio file that is playing.
102 * <p>
103 * <p>
104 * To indicate determinate progress, you set the style of the progress bar to
105 * {@link android.R.style#Widget_ProgressBar_Horizontal} and set the amount of progress.
106 * The following example shows a determinate progress bar that is 25% complete:
Scott Main42f139c2011-04-29 10:31:10 -0700107 * <pre>
Joe Fernandez72a9d592017-04-25 22:58:34 -0700108 * &lt;ProgressBar
109 * android:id="@+id/determinateBar"
110 * style="@android:style/Widget.ProgressBar.Horizontal"
111 * android:layout_width="wrap_content"
112 * android:layout_height="wrap_content"
113 * android:progress="25"/&gt;
114 * </pre>
115 * You can update the percentage of progress displayed by using the
116 * {@link #setProgress(int)} method, or by calling
117 * {@link #incrementProgressBy(int)} to increase the current progress completed
118 * by a specified amount.
119 * By default, the progress bar is full when the progress value reaches 100.
120 * You can adjust this default by setting the
121 * {@link android.R.styleable#ProgressBar_max android:max} attribute.
122 * </p>
Scott Main42f139c2011-04-29 10:31:10 -0700123 * <p>Other progress bar styles provided by the system include:</p>
124 * <ul>
125 * <li>{@link android.R.style#Widget_ProgressBar_Horizontal Widget.ProgressBar.Horizontal}</li>
126 * <li>{@link android.R.style#Widget_ProgressBar_Small Widget.ProgressBar.Small}</li>
127 * <li>{@link android.R.style#Widget_ProgressBar_Large Widget.ProgressBar.Large}</li>
128 * <li>{@link android.R.style#Widget_ProgressBar_Inverse Widget.ProgressBar.Inverse}</li>
129 * <li>{@link android.R.style#Widget_ProgressBar_Small_Inverse
130 * Widget.ProgressBar.Small.Inverse}</li>
131 * <li>{@link android.R.style#Widget_ProgressBar_Large_Inverse
132 * Widget.ProgressBar.Large.Inverse}</li>
133 * </ul>
134 * <p>The "inverse" styles provide an inverse color scheme for the spinner, which may be necessary
135 * if your application uses a light colored theme (a white background).</p>
RoboErik5b071432015-02-11 13:52:05 -0800136 *
137 * <p><strong>XML attributes</b></strong>
138 * <p>
139 * See {@link android.R.styleable#ProgressBar ProgressBar Attributes},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 * {@link android.R.styleable#View View Attributes}
141 * </p>
RoboErik5b071432015-02-11 13:52:05 -0800142 *
Scott Main42f139c2011-04-29 10:31:10 -0700143 * @attr ref android.R.styleable#ProgressBar_animationResolution
144 * @attr ref android.R.styleable#ProgressBar_indeterminate
145 * @attr ref android.R.styleable#ProgressBar_indeterminateBehavior
146 * @attr ref android.R.styleable#ProgressBar_indeterminateDrawable
147 * @attr ref android.R.styleable#ProgressBar_indeterminateDuration
148 * @attr ref android.R.styleable#ProgressBar_indeterminateOnly
149 * @attr ref android.R.styleable#ProgressBar_interpolator
Keyvan Amiri86fb2a22016-09-29 17:53:24 -0700150 * @attr ref android.R.styleable#ProgressBar_min
Scott Main42f139c2011-04-29 10:31:10 -0700151 * @attr ref android.R.styleable#ProgressBar_max
152 * @attr ref android.R.styleable#ProgressBar_maxHeight
153 * @attr ref android.R.styleable#ProgressBar_maxWidth
154 * @attr ref android.R.styleable#ProgressBar_minHeight
155 * @attr ref android.R.styleable#ProgressBar_minWidth
Scott Mainb40c1fd2013-04-23 13:30:06 -0700156 * @attr ref android.R.styleable#ProgressBar_mirrorForRtl
Scott Main42f139c2011-04-29 10:31:10 -0700157 * @attr ref android.R.styleable#ProgressBar_progress
158 * @attr ref android.R.styleable#ProgressBar_progressDrawable
159 * @attr ref android.R.styleable#ProgressBar_secondaryProgress
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 */
161@RemoteView
162public class ProgressBar extends View {
Alan Viverettea64ed3b2015-09-23 10:01:45 -0400163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 private static final int MAX_LEVEL = 10000;
Svetoslav Ganov6518ad72011-03-18 16:19:55 -0700165 private static final int TIMEOUT_SEND_ACCESSIBILITY_EVENT = 200;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166
Alan Viverettea64ed3b2015-09-23 10:01:45 -0400167 /** Interpolator used for smooth progress animations. */
168 private static final DecelerateInterpolator PROGRESS_ANIM_INTERPOLATOR =
169 new DecelerateInterpolator();
170
171 /** Duration of smooth progress animations. */
172 private static final int PROGRESS_ANIM_DURATION = 80;
173
Mihai Popacbc059d2019-02-05 18:35:29 +0000174 /**
175 * Outside the framework, please use {@link ProgressBar#getMinWidth()} and
176 * {@link ProgressBar#setMinWidth(int)} instead of accessing these directly.
177 */
178 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 int mMinWidth;
180 int mMaxWidth;
Mihai Popacbc059d2019-02-05 18:35:29 +0000181 /**
182 * Outside the framework, please use {@link ProgressBar#getMinHeight()} and
183 * {@link ProgressBar#setMinHeight(int)} instead of accessing these directly.
184 */
185 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 int mMinHeight;
Mihai Popacbc059d2019-02-05 18:35:29 +0000187 /**
188 * Outside the framework, please use {@link ProgressBar#getMaxHeight()} ()} and
189 * {@link ProgressBar#setMaxHeight(int)} (int)} instead of accessing these directly.
190 */
191 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 int mMaxHeight;
193
194 private int mProgress;
195 private int mSecondaryProgress;
Keyvan Amiri86fb2a22016-09-29 17:53:24 -0700196 private int mMin;
197 private boolean mMinInitialized;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 private int mMax;
Keyvan Amiri86fb2a22016-09-29 17:53:24 -0700199 private boolean mMaxInitialized;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
201 private int mBehavior;
shepshapard3b070452019-02-08 16:54:55 -0800202 // Better to define a Drawable that implements Animatable if you want to modify animation
203 // characteristics programatically.
204 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124052713)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 private int mDuration;
Adam Powell84113362019-02-05 13:32:47 -0800206 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 private boolean mIndeterminate;
Sumir Kataria08b675372019-02-08 11:31:22 -0800208 @UnsupportedAppUsage(trackingBug = 124049927)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 private boolean mOnlyIndeterminate;
210 private Transformation mTransformation;
211 private AlphaAnimation mAnimation;
Romain Guyab4c4f4f2012-05-06 13:11:24 -0700212 private boolean mHasAnimation;
Alan Viverette91174362014-06-17 14:51:45 -0700213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 private Drawable mIndeterminateDrawable;
215 private Drawable mProgressDrawable;
Mihai Popa3df49262019-02-06 12:35:29 +0000216 /**
217 * Outside the framework, instead of accessing this directly, please use
218 * {@link #getCurrentDrawable()}, {@link #setProgressDrawable(Drawable)},
219 * {@link #setIndeterminateDrawable(Drawable)} and their tiled versions.
220 */
221 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 private Drawable mCurrentDrawable;
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700223 private ProgressTintInfo mProgressTintInfo;
224
Alan Viverette0d2a46b2016-10-07 16:23:32 -0400225 int mSampleWidth = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 private boolean mNoInvalidate;
227 private Interpolator mInterpolator;
228 private RefreshProgressRunnable mRefreshProgressRunnable;
229 private long mUiThreadId;
230 private boolean mShouldStartAnimationDrawable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231
232 private boolean mInDrawing;
Adam Powella0506632012-04-10 17:19:20 -0700233 private boolean mAttached;
234 private boolean mRefreshIsPosted;
235
Alan Viverettea64ed3b2015-09-23 10:01:45 -0400236 /** Value used to track progress animation, in the range [0...1]. */
237 private float mVisualProgress;
238
Mathew Inwood978c6e22018-08-21 15:58:55 +0100239 @UnsupportedAppUsage
Fabrice Di Meglio2b378cd2013-01-30 16:39:33 -0800240 boolean mMirrorForRtl = false;
241
Adam Powell41d96902016-03-15 14:43:19 -0700242 private boolean mAggregatedIsVisible;
243
Adam Powella0506632012-04-10 17:19:20 -0700244 private final ArrayList<RefreshData> mRefreshData = new ArrayList<RefreshData>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245
Svetoslav Ganov6518ad72011-03-18 16:19:55 -0700246 private AccessibilityEventSender mAccessibilityEventSender;
247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 /**
249 * Create a new progress bar with range 0...100 and initial progress of 0.
250 * @param context the application environment
251 */
252 public ProgressBar(Context context) {
253 this(context, null);
254 }
RoboErik5b071432015-02-11 13:52:05 -0800255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 public ProgressBar(Context context, AttributeSet attrs) {
257 this(context, attrs, com.android.internal.R.attr.progressBarStyle);
258 }
259
Alan Viverette617feb92013-09-09 18:09:13 -0700260 public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
261 this(context, attrs, defStyleAttr, 0);
Adam Powell6af97e12010-11-11 21:11:53 -0800262 }
263
Alan Viverette617feb92013-09-09 18:09:13 -0700264 public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
265 super(context, attrs, defStyleAttr, defStyleRes);
266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 mUiThreadId = Thread.currentThread().getId();
268 initProgressBar();
269
Alan Viverette617feb92013-09-09 18:09:13 -0700270 final TypedArray a = context.obtainStyledAttributes(
271 attrs, R.styleable.ProgressBar, defStyleAttr, defStyleRes);
Aurimas Liutikasab324cf2019-02-07 16:46:38 -0800272 saveAttributeDataForStyleable(context, R.styleable.ProgressBar,
273 attrs, a, defStyleAttr, defStyleRes);
RoboErik5b071432015-02-11 13:52:05 -0800274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 mNoInvalidate = true;
RoboErik5b071432015-02-11 13:52:05 -0800276
Alan Viverette91174362014-06-17 14:51:45 -0700277 final Drawable progressDrawable = a.getDrawable(R.styleable.ProgressBar_progressDrawable);
278 if (progressDrawable != null) {
Alan Viveretteff9f7b962015-04-08 10:49:26 -0700279 // Calling setProgressDrawable can set mMaxHeight, so make sure the
280 // corresponding XML attribute for mMaxHeight is read after calling
281 // this method.
282 if (needsTileify(progressDrawable)) {
283 setProgressDrawableTiled(progressDrawable);
284 } else {
285 setProgressDrawable(progressDrawable);
286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 }
288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 mDuration = a.getInt(R.styleable.ProgressBar_indeterminateDuration, mDuration);
290
291 mMinWidth = a.getDimensionPixelSize(R.styleable.ProgressBar_minWidth, mMinWidth);
292 mMaxWidth = a.getDimensionPixelSize(R.styleable.ProgressBar_maxWidth, mMaxWidth);
293 mMinHeight = a.getDimensionPixelSize(R.styleable.ProgressBar_minHeight, mMinHeight);
294 mMaxHeight = a.getDimensionPixelSize(R.styleable.ProgressBar_maxHeight, mMaxHeight);
295
296 mBehavior = a.getInt(R.styleable.ProgressBar_indeterminateBehavior, mBehavior);
297
Jean-Baptiste Queru72b1f372009-08-31 09:17:57 -0700298 final int resID = a.getResourceId(
RoboErik5b071432015-02-11 13:52:05 -0800299 com.android.internal.R.styleable.ProgressBar_interpolator,
Jean-Baptiste Queru72b1f372009-08-31 09:17:57 -0700300 android.R.anim.linear_interpolator); // default to linear interpolator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 if (resID > 0) {
302 setInterpolator(context, resID);
RoboErik5b071432015-02-11 13:52:05 -0800303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304
Keyvan Amiri86fb2a22016-09-29 17:53:24 -0700305 setMin(a.getInt(R.styleable.ProgressBar_min, mMin));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 setMax(a.getInt(R.styleable.ProgressBar_max, mMax));
307
308 setProgress(a.getInt(R.styleable.ProgressBar_progress, mProgress));
309
Alan Viveretteff9f7b962015-04-08 10:49:26 -0700310 setSecondaryProgress(a.getInt(
311 R.styleable.ProgressBar_secondaryProgress, mSecondaryProgress));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312
Alan Viverette91174362014-06-17 14:51:45 -0700313 final Drawable indeterminateDrawable = a.getDrawable(
314 R.styleable.ProgressBar_indeterminateDrawable);
315 if (indeterminateDrawable != null) {
Alan Viveretteff9f7b962015-04-08 10:49:26 -0700316 if (needsTileify(indeterminateDrawable)) {
317 setIndeterminateDrawableTiled(indeterminateDrawable);
318 } else {
319 setIndeterminateDrawable(indeterminateDrawable);
320 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 }
322
323 mOnlyIndeterminate = a.getBoolean(
324 R.styleable.ProgressBar_indeterminateOnly, mOnlyIndeterminate);
325
326 mNoInvalidate = false;
327
328 setIndeterminate(mOnlyIndeterminate || a.getBoolean(
329 R.styleable.ProgressBar_indeterminate, mIndeterminate));
330
Fabrice Di Meglio2b378cd2013-01-30 16:39:33 -0800331 mMirrorForRtl = a.getBoolean(R.styleable.ProgressBar_mirrorForRtl, mMirrorForRtl);
332
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700333 if (a.hasValue(R.styleable.ProgressBar_progressTintMode)) {
334 if (mProgressTintInfo == null) {
335 mProgressTintInfo = new ProgressTintInfo();
336 }
337 mProgressTintInfo.mProgressTintMode = Drawable.parseTintMode(a.getInt(
Alan Viverettedbc40182015-04-06 15:01:23 -0700338 R.styleable.ProgressBar_progressTintMode, -1), null);
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700339 mProgressTintInfo.mHasProgressTintMode = true;
340 }
Alan Viverette4f64c042014-07-21 17:49:13 -0700341
Alan Viverette91174362014-06-17 14:51:45 -0700342 if (a.hasValue(R.styleable.ProgressBar_progressTint)) {
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700343 if (mProgressTintInfo == null) {
344 mProgressTintInfo = new ProgressTintInfo();
345 }
346 mProgressTintInfo.mProgressTintList = a.getColorStateList(
Alan Viverette91174362014-06-17 14:51:45 -0700347 R.styleable.ProgressBar_progressTint);
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700348 mProgressTintInfo.mHasProgressTint = true;
Alan Viverette91174362014-06-17 14:51:45 -0700349 }
350
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700351 if (a.hasValue(R.styleable.ProgressBar_progressBackgroundTintMode)) {
352 if (mProgressTintInfo == null) {
353 mProgressTintInfo = new ProgressTintInfo();
354 }
355 mProgressTintInfo.mProgressBackgroundTintMode = Drawable.parseTintMode(a.getInt(
Alan Viverettedbc40182015-04-06 15:01:23 -0700356 R.styleable.ProgressBar_progressBackgroundTintMode, -1), null);
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700357 mProgressTintInfo.mHasProgressBackgroundTintMode = true;
358 }
Alan Viverette4f64c042014-07-21 17:49:13 -0700359
Alan Viverette91174362014-06-17 14:51:45 -0700360 if (a.hasValue(R.styleable.ProgressBar_progressBackgroundTint)) {
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700361 if (mProgressTintInfo == null) {
362 mProgressTintInfo = new ProgressTintInfo();
363 }
364 mProgressTintInfo.mProgressBackgroundTintList = a.getColorStateList(
Alan Viverette91174362014-06-17 14:51:45 -0700365 R.styleable.ProgressBar_progressBackgroundTint);
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700366 mProgressTintInfo.mHasProgressBackgroundTint = true;
Alan Viverette91174362014-06-17 14:51:45 -0700367 }
368
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700369 if (a.hasValue(R.styleable.ProgressBar_secondaryProgressTintMode)) {
370 if (mProgressTintInfo == null) {
371 mProgressTintInfo = new ProgressTintInfo();
372 }
373 mProgressTintInfo.mSecondaryProgressTintMode = Drawable.parseTintMode(
374 a.getInt(R.styleable.ProgressBar_secondaryProgressTintMode, -1), null);
375 mProgressTintInfo.mHasSecondaryProgressTintMode = true;
376 }
Alan Viverette4f64c042014-07-21 17:49:13 -0700377
Alan Viverette91174362014-06-17 14:51:45 -0700378 if (a.hasValue(R.styleable.ProgressBar_secondaryProgressTint)) {
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700379 if (mProgressTintInfo == null) {
380 mProgressTintInfo = new ProgressTintInfo();
381 }
382 mProgressTintInfo.mSecondaryProgressTintList = a.getColorStateList(
Alan Viverette91174362014-06-17 14:51:45 -0700383 R.styleable.ProgressBar_secondaryProgressTint);
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700384 mProgressTintInfo.mHasSecondaryProgressTint = true;
Alan Viverette91174362014-06-17 14:51:45 -0700385 }
386
Alan Viverettedbc40182015-04-06 15:01:23 -0700387 if (a.hasValue(R.styleable.ProgressBar_indeterminateTintMode)) {
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700388 if (mProgressTintInfo == null) {
389 mProgressTintInfo = new ProgressTintInfo();
390 }
391 mProgressTintInfo.mIndeterminateTintMode = Drawable.parseTintMode(a.getInt(
392 R.styleable.ProgressBar_indeterminateTintMode, -1), null);
393 mProgressTintInfo.mHasIndeterminateTintMode = true;
394 }
Alan Viverette4f64c042014-07-21 17:49:13 -0700395
Alan Viverette91174362014-06-17 14:51:45 -0700396 if (a.hasValue(R.styleable.ProgressBar_indeterminateTint)) {
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700397 if (mProgressTintInfo == null) {
398 mProgressTintInfo = new ProgressTintInfo();
399 }
400 mProgressTintInfo.mIndeterminateTintList = a.getColorStateList(
Alan Viverette91174362014-06-17 14:51:45 -0700401 R.styleable.ProgressBar_indeterminateTint);
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700402 mProgressTintInfo.mHasIndeterminateTint = true;
Alan Viverette91174362014-06-17 14:51:45 -0700403 }
404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 a.recycle();
Svetoslav7face752014-01-13 15:25:58 -0800406
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700407 applyProgressTints();
408 applyIndeterminateTint();
409
Svetoslav7face752014-01-13 15:25:58 -0800410 // If not explicitly specified this view is important for accessibility.
411 if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
412 setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 }
415
416 /**
Mihai Popacbc059d2019-02-05 18:35:29 +0000417 * Sets the minimum width the progress bar can have.
418 * @param minWidth the minimum width to be set, in pixels
419 * @attr ref android.R.styleable#ProgressBar_minWidth
420 */
421 public void setMinWidth(@Px int minWidth) {
422 mMinWidth = minWidth;
423 requestLayout();
424 }
425
426 /**
427 * @return the minimum width the progress bar can have, in pixels
428 */
429 @Px public int getMinWidth() {
430 return mMinWidth;
431 }
432
433 /**
434 * Sets the maximum width the progress bar can have.
435 * @param maxWidth the maximum width to be set, in pixels
436 * @attr ref android.R.styleable#ProgressBar_maxWidth
437 */
438 public void setMaxWidth(@Px int maxWidth) {
439 mMaxWidth = maxWidth;
440 requestLayout();
441 }
442
443 /**
444 * @return the maximum width the progress bar can have, in pixels
445 */
446 @Px public int getMaxWidth() {
447 return mMaxWidth;
448 }
449
450 /**
451 * Sets the minimum height the progress bar can have.
452 * @param minHeight the minimum height to be set, in pixels
453 * @attr ref android.R.styleable#ProgressBar_minHeight
454 */
455 public void setMinHeight(@Px int minHeight) {
456 mMinHeight = minHeight;
457 requestLayout();
458 }
459
460 /**
461 * @return the minimum height the progress bar can have, in pixels
462 */
463 @Px public int getMinHeight() {
464 return mMinHeight;
465 }
466
467 /**
468 * Sets the maximum height the progress bar can have.
469 * @param maxHeight the maximum height to be set, in pixels
470 * @attr ref android.R.styleable#ProgressBar_maxHeight
471 */
472 public void setMaxHeight(@Px int maxHeight) {
473 mMaxHeight = maxHeight;
474 requestLayout();
475 }
476
477 /**
478 * @return the maximum height the progress bar can have, in pixels
479 */
480 @Px public int getMaxHeight() {
481 return mMaxHeight;
482 }
483
484 /**
Alan Viveretteff9f7b962015-04-08 10:49:26 -0700485 * Returns {@code true} if the target drawable needs to be tileified.
486 *
487 * @param dr the drawable to check
488 * @return {@code true} if the target drawable needs to be tileified,
489 * {@code false} otherwise
490 */
491 private static boolean needsTileify(Drawable dr) {
492 if (dr instanceof LayerDrawable) {
493 final LayerDrawable orig = (LayerDrawable) dr;
494 final int N = orig.getNumberOfLayers();
495 for (int i = 0; i < N; i++) {
496 if (needsTileify(orig.getDrawable(i))) {
497 return true;
498 }
499 }
500 return false;
501 }
502
503 if (dr instanceof StateListDrawable) {
504 final StateListDrawable in = (StateListDrawable) dr;
505 final int N = in.getStateCount();
506 for (int i = 0; i < N; i++) {
507 if (needsTileify(in.getStateDrawable(i))) {
508 return true;
509 }
510 }
511 return false;
512 }
513
514 // If there's a bitmap that's not wrapped with a ClipDrawable or
515 // ScaleDrawable, we'll need to wrap it and apply tiling.
516 if (dr instanceof BitmapDrawable) {
517 return true;
518 }
519
520 return false;
521 }
522
523 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 * Converts a drawable to a tiled version of itself. It will recursively
525 * traverse layer and state list drawables.
526 */
Mathew Inwood978c6e22018-08-21 15:58:55 +0100527 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 private Drawable tileify(Drawable drawable, boolean clip) {
Alan Viverette6a8253f2015-02-23 12:49:47 -0800529 // TODO: This is a terrible idea that potentially destroys any drawable
530 // that extends any of these classes. We *really* need to remove this.
RoboErik5b071432015-02-11 13:52:05 -0800531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 if (drawable instanceof LayerDrawable) {
Alan Viverette6a8253f2015-02-23 12:49:47 -0800533 final LayerDrawable orig = (LayerDrawable) drawable;
534 final int N = orig.getNumberOfLayers();
535 final Drawable[] outDrawables = new Drawable[N];
RoboErik5b071432015-02-11 13:52:05 -0800536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 for (int i = 0; i < N; i++) {
Alan Viverette6a8253f2015-02-23 12:49:47 -0800538 final int id = orig.getId(i);
539 outDrawables[i] = tileify(orig.getDrawable(i),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 (id == R.id.progress || id == R.id.secondaryProgress));
541 }
542
Alan Viverette6a8253f2015-02-23 12:49:47 -0800543 final LayerDrawable clone = new LayerDrawable(outDrawables);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800544 for (int i = 0; i < N; i++) {
Alan Viverette6a8253f2015-02-23 12:49:47 -0800545 clone.setId(i, orig.getId(i));
546 clone.setLayerGravity(i, orig.getLayerGravity(i));
547 clone.setLayerWidth(i, orig.getLayerWidth(i));
548 clone.setLayerHeight(i, orig.getLayerHeight(i));
549 clone.setLayerInsetLeft(i, orig.getLayerInsetLeft(i));
550 clone.setLayerInsetRight(i, orig.getLayerInsetRight(i));
551 clone.setLayerInsetTop(i, orig.getLayerInsetTop(i));
552 clone.setLayerInsetBottom(i, orig.getLayerInsetBottom(i));
553 clone.setLayerInsetStart(i, orig.getLayerInsetStart(i));
554 clone.setLayerInsetEnd(i, orig.getLayerInsetEnd(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 }
RoboErik5b071432015-02-11 13:52:05 -0800556
Alan Viverette6a8253f2015-02-23 12:49:47 -0800557 return clone;
558 }
RoboErik5b071432015-02-11 13:52:05 -0800559
Alan Viverette6a8253f2015-02-23 12:49:47 -0800560 if (drawable instanceof StateListDrawable) {
561 final StateListDrawable in = (StateListDrawable) drawable;
562 final StateListDrawable out = new StateListDrawable();
563 final int N = in.getStateCount();
564 for (int i = 0; i < N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 out.addState(in.getStateSet(i), tileify(in.getStateDrawable(i), clip));
566 }
RoboErik5b071432015-02-11 13:52:05 -0800567
Alan Viverette6a8253f2015-02-23 12:49:47 -0800568 return out;
569 }
570
571 if (drawable instanceof BitmapDrawable) {
Alan Viverette0d2a46b2016-10-07 16:23:32 -0400572 final Drawable.ConstantState cs = drawable.getConstantState();
573 final BitmapDrawable clone = (BitmapDrawable) cs.newDrawable(getResources());
Alan Viveretteff9f7b962015-04-08 10:49:26 -0700574 clone.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575
Alan Viverette0d2a46b2016-10-07 16:23:32 -0400576 if (mSampleWidth <= 0) {
577 mSampleWidth = clone.getIntrinsicWidth();
578 }
579
Alan Viveretteff9f7b962015-04-08 10:49:26 -0700580 if (clip) {
581 return new ClipDrawable(clone, Gravity.LEFT, ClipDrawable.HORIZONTAL);
582 } else {
583 return clone;
584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 }
RoboErik5b071432015-02-11 13:52:05 -0800586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 return drawable;
588 }
589
590 Shape getDrawableShape() {
591 final float[] roundedCorners = new float[] { 5, 5, 5, 5, 5, 5, 5, 5 };
592 return new RoundRectShape(roundedCorners, null, null);
593 }
RoboErik5b071432015-02-11 13:52:05 -0800594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 /**
596 * Convert a AnimationDrawable for use as a barberpole animation.
597 * Each frame of the animation is wrapped in a ClipDrawable and
598 * given a tiling BitmapShader.
599 */
600 private Drawable tileifyIndeterminate(Drawable drawable) {
601 if (drawable instanceof AnimationDrawable) {
602 AnimationDrawable background = (AnimationDrawable) drawable;
603 final int N = background.getNumberOfFrames();
604 AnimationDrawable newBg = new AnimationDrawable();
605 newBg.setOneShot(background.isOneShot());
RoboErik5b071432015-02-11 13:52:05 -0800606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800607 for (int i = 0; i < N; i++) {
608 Drawable frame = tileify(background.getFrame(i), true);
609 frame.setLevel(10000);
610 newBg.addFrame(frame, background.getDuration(i));
611 }
612 newBg.setLevel(10000);
613 drawable = newBg;
614 }
615 return drawable;
616 }
RoboErik5b071432015-02-11 13:52:05 -0800617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 /**
619 * <p>
620 * Initialize the progress bar's default values:
621 * </p>
622 * <ul>
623 * <li>progress = 0</li>
624 * <li>max = 100</li>
625 * <li>animation duration = 4000 ms</li>
626 * <li>indeterminate = false</li>
627 * <li>behavior = repeat</li>
628 * </ul>
629 */
630 private void initProgressBar() {
Keyvan Amiri86fb2a22016-09-29 17:53:24 -0700631 mMin = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 mMax = 100;
633 mProgress = 0;
634 mSecondaryProgress = 0;
635 mIndeterminate = false;
636 mOnlyIndeterminate = false;
637 mDuration = 4000;
638 mBehavior = AlphaAnimation.RESTART;
639 mMinWidth = 24;
640 mMaxWidth = 48;
641 mMinHeight = 24;
642 mMaxHeight = 48;
643 }
644
645 /**
646 * <p>Indicate whether this progress bar is in indeterminate mode.</p>
647 *
648 * @return true if the progress bar is in indeterminate mode
649 */
Ashley Rose55f9f922019-01-28 19:29:36 -0500650 @InspectableProperty
Konstantin Lopyrevbea95162010-08-10 17:02:18 -0700651 @ViewDebug.ExportedProperty(category = "progress")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 public synchronized boolean isIndeterminate() {
653 return mIndeterminate;
654 }
655
656 /**
657 * <p>Change the indeterminate mode for this progress bar. In indeterminate
658 * mode, the progress is ignored and the progress bar shows an infinite
659 * animation instead.</p>
RoboErik5b071432015-02-11 13:52:05 -0800660 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661 * If this progress bar's style only supports indeterminate mode (such as the circular
662 * progress bars), then this will be ignored.
663 *
664 * @param indeterminate true to enable the indeterminate mode
665 */
666 @android.view.RemotableViewMethod
667 public synchronized void setIndeterminate(boolean indeterminate) {
668 if ((!mOnlyIndeterminate || !mIndeterminate) && indeterminate != mIndeterminate) {
669 mIndeterminate = indeterminate;
670
671 if (indeterminate) {
672 // swap between indeterminate and regular backgrounds
Adam Powellc1bba9b2016-03-03 16:51:17 -0800673 swapCurrentDrawable(mIndeterminateDrawable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 startAnimation();
675 } else {
Adam Powellc1bba9b2016-03-03 16:51:17 -0800676 swapCurrentDrawable(mProgressDrawable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677 stopAnimation();
678 }
679 }
680 }
681
Adam Powellc1bba9b2016-03-03 16:51:17 -0800682 private void swapCurrentDrawable(Drawable newDrawable) {
683 final Drawable oldDrawable = mCurrentDrawable;
684 mCurrentDrawable = newDrawable;
Adam Powell9c146bf2016-03-15 17:35:00 -0700685
Adam Powellc1bba9b2016-03-03 16:51:17 -0800686 if (oldDrawable != mCurrentDrawable) {
687 if (oldDrawable != null) {
688 oldDrawable.setVisible(false, false);
689 }
690 if (mCurrentDrawable != null) {
Adam Powell41d96902016-03-15 14:43:19 -0700691 mCurrentDrawable.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
Adam Powellc1bba9b2016-03-03 16:51:17 -0800692 }
693 }
694 }
695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696 /**
697 * <p>Get the drawable used to draw the progress bar in
698 * indeterminate mode.</p>
699 *
700 * @return a {@link android.graphics.drawable.Drawable} instance
701 *
702 * @see #setIndeterminateDrawable(android.graphics.drawable.Drawable)
703 * @see #setIndeterminate(boolean)
704 */
Ashley Rose55f9f922019-01-28 19:29:36 -0500705 @InspectableProperty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 public Drawable getIndeterminateDrawable() {
707 return mIndeterminateDrawable;
708 }
709
710 /**
Alan Viverettee785d022013-09-26 15:21:10 -0700711 * Define the drawable used to draw the progress bar in indeterminate mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 *
shepshapard3b070452019-02-08 16:54:55 -0800713 * <p>For the Drawable to animate, it must implement {@link Animatable}, or override
714 * {@link Drawable#onLevelChange(int)}. A Drawable that implements Animatable will be animated
715 * via that interface and therefore provides the greatest amount of customization. A Drawable
716 * that only overrides onLevelChange(int) is animated directly by ProgressBar and only the
717 * animation {@link android.R.styleable#ProgressBar_indeterminateDuration duration},
718 * {@link android.R.styleable#ProgressBar_indeterminateBehavior repeating behavior}, and
719 * {@link #setInterpolator(Interpolator) interpolator} can be modified, and only before the
720 * indeterminate animation begins.
721 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722 * @param d the new drawable
shepshapard3b070452019-02-08 16:54:55 -0800723 * @attr ref android.R.styleable#ProgressBar_indeterminateDrawable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800724 * @see #getIndeterminateDrawable()
725 * @see #setIndeterminate(boolean)
726 */
727 public void setIndeterminateDrawable(Drawable d) {
Alan Viverette91174362014-06-17 14:51:45 -0700728 if (mIndeterminateDrawable != d) {
729 if (mIndeterminateDrawable != null) {
730 mIndeterminateDrawable.setCallback(null);
731 unscheduleDrawable(mIndeterminateDrawable);
732 }
733
734 mIndeterminateDrawable = d;
735
736 if (d != null) {
737 d.setCallback(this);
738 d.setLayoutDirection(getLayoutDirection());
739 if (d.isStateful()) {
740 d.setState(getDrawableState());
741 }
742 applyIndeterminateTint();
743 }
744
745 if (mIndeterminate) {
Adam Powellc1bba9b2016-03-03 16:51:17 -0800746 swapCurrentDrawable(d);
Alan Viverette91174362014-06-17 14:51:45 -0700747 postInvalidate();
748 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 }
Alan Viverette91174362014-06-17 14:51:45 -0700750 }
751
752 /**
Alan Viverette91174362014-06-17 14:51:45 -0700753 * Applies a tint to the indeterminate drawable. Does not modify the
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700754 * current tint mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
Alan Viverette91174362014-06-17 14:51:45 -0700755 * <p>
756 * Subsequent calls to {@link #setIndeterminateDrawable(Drawable)} will
757 * automatically mutate the drawable and apply the specified tint and
758 * tint mode using
Alan Viverettea4264452014-07-28 16:02:55 -0700759 * {@link Drawable#setTintList(ColorStateList)}.
Alan Viverette91174362014-06-17 14:51:45 -0700760 *
761 * @param tint the tint to apply, may be {@code null} to clear tint
762 *
763 * @attr ref android.R.styleable#ProgressBar_indeterminateTint
Alan Viverettea4264452014-07-28 16:02:55 -0700764 * @see #getIndeterminateTintList()
765 * @see Drawable#setTintList(ColorStateList)
Alan Viverette91174362014-06-17 14:51:45 -0700766 */
Jorim Jaggief72a192014-08-26 21:57:46 +0200767 @RemotableViewMethod
Alan Viverettea4264452014-07-28 16:02:55 -0700768 public void setIndeterminateTintList(@Nullable ColorStateList tint) {
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700769 if (mProgressTintInfo == null) {
770 mProgressTintInfo = new ProgressTintInfo();
771 }
772 mProgressTintInfo.mIndeterminateTintList = tint;
773 mProgressTintInfo.mHasIndeterminateTint = true;
Alan Viverette4f64c042014-07-21 17:49:13 -0700774
775 applyIndeterminateTint();
Alan Viverette91174362014-06-17 14:51:45 -0700776 }
777
778 /**
779 * @return the tint applied to the indeterminate drawable
780 * @attr ref android.R.styleable#ProgressBar_indeterminateTint
Alan Viverettea4264452014-07-28 16:02:55 -0700781 * @see #setIndeterminateTintList(ColorStateList)
Alan Viverette91174362014-06-17 14:51:45 -0700782 */
Ashley Rose55f9f922019-01-28 19:29:36 -0500783 @InspectableProperty(name = "indeterminateTint")
Alan Viverette91174362014-06-17 14:51:45 -0700784 @Nullable
Alan Viverettea4264452014-07-28 16:02:55 -0700785 public ColorStateList getIndeterminateTintList() {
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700786 return mProgressTintInfo != null ? mProgressTintInfo.mIndeterminateTintList : null;
Alan Viverette91174362014-06-17 14:51:45 -0700787 }
788
789 /**
790 * Specifies the blending mode used to apply the tint specified by
Alan Viverettea4264452014-07-28 16:02:55 -0700791 * {@link #setIndeterminateTintList(ColorStateList)} to the indeterminate
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700792 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
Alan Viverette91174362014-06-17 14:51:45 -0700793 *
794 * @param tintMode the blending mode used to apply the tint, may be
795 * {@code null} to clear tint
796 * @attr ref android.R.styleable#ProgressBar_indeterminateTintMode
Alan Viverettea4264452014-07-28 16:02:55 -0700797 * @see #setIndeterminateTintList(ColorStateList)
798 * @see Drawable#setTintMode(PorterDuff.Mode)
Alan Viverette91174362014-06-17 14:51:45 -0700799 */
800 public void setIndeterminateTintMode(@Nullable PorterDuff.Mode tintMode) {
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700801 if (mProgressTintInfo == null) {
802 mProgressTintInfo = new ProgressTintInfo();
803 }
804 mProgressTintInfo.mIndeterminateTintMode = tintMode;
805 mProgressTintInfo.mHasIndeterminateTintMode = true;
Alan Viverette4f64c042014-07-21 17:49:13 -0700806
807 applyIndeterminateTint();
Alan Viverette91174362014-06-17 14:51:45 -0700808 }
809
810 /**
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700811 * Returns the blending mode used to apply the tint to the indeterminate
812 * drawable, if specified.
813 *
814 * @return the blending mode used to apply the tint to the indeterminate
815 * drawable
Alan Viverette91174362014-06-17 14:51:45 -0700816 * @attr ref android.R.styleable#ProgressBar_indeterminateTintMode
Alan Viverette4f64c042014-07-21 17:49:13 -0700817 * @see #setIndeterminateTintMode(PorterDuff.Mode)
Alan Viverette91174362014-06-17 14:51:45 -0700818 */
Ashley Rose55f9f922019-01-28 19:29:36 -0500819 @InspectableProperty
Alan Viverette91174362014-06-17 14:51:45 -0700820 @Nullable
821 public PorterDuff.Mode getIndeterminateTintMode() {
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700822 return mProgressTintInfo != null ? mProgressTintInfo.mIndeterminateTintMode : null;
Alan Viverette91174362014-06-17 14:51:45 -0700823 }
824
825 private void applyIndeterminateTint() {
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700826 if (mIndeterminateDrawable != null && mProgressTintInfo != null) {
827 final ProgressTintInfo tintInfo = mProgressTintInfo;
828 if (tintInfo.mHasIndeterminateTint || tintInfo.mHasIndeterminateTintMode) {
829 mIndeterminateDrawable = mIndeterminateDrawable.mutate();
830
831 if (tintInfo.mHasIndeterminateTint) {
832 mIndeterminateDrawable.setTintList(tintInfo.mIndeterminateTintList);
833 }
834
835 if (tintInfo.mHasIndeterminateTintMode) {
836 mIndeterminateDrawable.setTintMode(tintInfo.mIndeterminateTintMode);
837 }
Alan Viveretted5133792014-10-28 14:41:36 -0700838
839 // The drawable (or one of its children) may not have been
840 // stateful before applying the tint, so let's try again.
841 if (mIndeterminateDrawable.isStateful()) {
842 mIndeterminateDrawable.setState(getDrawableState());
843 }
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 }
846 }
Alan Viverettee785d022013-09-26 15:21:10 -0700847
848 /**
849 * Define the tileable drawable used to draw the progress bar in
850 * indeterminate mode.
851 * <p>
852 * If the drawable is a BitmapDrawable or contains BitmapDrawables, a
853 * tiled copy will be generated for display as a progress bar.
854 *
855 * @param d the new drawable
856 * @see #getIndeterminateDrawable()
857 * @see #setIndeterminate(boolean)
858 */
859 public void setIndeterminateDrawableTiled(Drawable d) {
860 if (d != null) {
861 d = tileifyIndeterminate(d);
862 }
863
864 setIndeterminateDrawable(d);
865 }
RoboErik5b071432015-02-11 13:52:05 -0800866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 /**
868 * <p>Get the drawable used to draw the progress bar in
869 * progress mode.</p>
870 *
871 * @return a {@link android.graphics.drawable.Drawable} instance
872 *
873 * @see #setProgressDrawable(android.graphics.drawable.Drawable)
874 * @see #setIndeterminate(boolean)
875 */
Ashley Rose55f9f922019-01-28 19:29:36 -0500876 @InspectableProperty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877 public Drawable getProgressDrawable() {
878 return mProgressDrawable;
879 }
880
881 /**
Alan Viverettee785d022013-09-26 15:21:10 -0700882 * Define the drawable used to draw the progress bar in progress mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 *
884 * @param d the new drawable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800885 * @see #getProgressDrawable()
886 * @see #setIndeterminate(boolean)
887 */
888 public void setProgressDrawable(Drawable d) {
Alan Viverette91174362014-06-17 14:51:45 -0700889 if (mProgressDrawable != d) {
890 if (mProgressDrawable != null) {
891 mProgressDrawable.setCallback(null);
892 unscheduleDrawable(mProgressDrawable);
893 }
Joe Onoratoaa072632010-12-08 15:31:28 -0800894
Alan Viverette91174362014-06-17 14:51:45 -0700895 mProgressDrawable = d;
896
897 if (d != null) {
898 d.setCallback(this);
Fabrice Di Meglioe56ffdc2012-09-23 14:51:16 -0700899 d.setLayoutDirection(getLayoutDirection());
Alan Viverette91174362014-06-17 14:51:45 -0700900 if (d.isStateful()) {
901 d.setState(getDrawableState());
902 }
903
904 // Make sure the ProgressBar is always tall enough
905 int drawableHeight = d.getMinimumHeight();
906 if (mMaxHeight < drawableHeight) {
907 mMaxHeight = drawableHeight;
908 requestLayout();
909 }
910
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700911 applyProgressTints();
Fabrice Di Meglio0af4b8b2012-06-11 18:30:05 -0700912 }
NoraBoraa7f7e2a2009-12-25 19:51:34 -0500913
Alan Viverette91174362014-06-17 14:51:45 -0700914 if (!mIndeterminate) {
Adam Powellc1bba9b2016-03-03 16:51:17 -0800915 swapCurrentDrawable(d);
Alan Viverette91174362014-06-17 14:51:45 -0700916 postInvalidate();
NoraBoraa7f7e2a2009-12-25 19:51:34 -0500917 }
Joe Onoratoaa072632010-12-08 15:31:28 -0800918
Joe Onoratoaa072632010-12-08 15:31:28 -0800919 updateDrawableBounds(getWidth(), getHeight());
920 updateDrawableState();
Alan Viverette91174362014-06-17 14:51:45 -0700921
Alan Viverettea64ed3b2015-09-23 10:01:45 -0400922 doRefreshProgress(R.id.progress, mProgress, false, false, false);
923 doRefreshProgress(R.id.secondaryProgress, mSecondaryProgress, false, false, false);
Joe Onoratoaa072632010-12-08 15:31:28 -0800924 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 }
Alan Viverettee785d022013-09-26 15:21:10 -0700926
927 /**
Christine Franks6418d0b2017-02-13 09:48:00 -0800928 * @hide
929 */
Ashley Rose55f9f922019-01-28 19:29:36 -0500930 @InspectableProperty
Christine Franks6418d0b2017-02-13 09:48:00 -0800931 public boolean getMirrorForRtl() {
932 return mMirrorForRtl;
933 }
934
935 /**
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700936 * Applies the progress tints in order of increasing specificity.
937 */
938 private void applyProgressTints() {
939 if (mProgressDrawable != null && mProgressTintInfo != null) {
940 applyPrimaryProgressTint();
941 applyProgressBackgroundTint();
942 applySecondaryProgressTint();
943 }
944 }
945
946 /**
947 * Should only be called if we've already verified that mProgressDrawable
948 * and mProgressTintInfo are non-null.
949 */
950 private void applyPrimaryProgressTint() {
951 if (mProgressTintInfo.mHasProgressTint
952 || mProgressTintInfo.mHasProgressTintMode) {
953 final Drawable target = getTintTarget(R.id.progress, true);
954 if (target != null) {
955 if (mProgressTintInfo.mHasProgressTint) {
956 target.setTintList(mProgressTintInfo.mProgressTintList);
957 }
958 if (mProgressTintInfo.mHasProgressTintMode) {
959 target.setTintMode(mProgressTintInfo.mProgressTintMode);
960 }
Alan Viveretted5133792014-10-28 14:41:36 -0700961
962 // The drawable (or one of its children) may not have been
963 // stateful before applying the tint, so let's try again.
964 if (target.isStateful()) {
965 target.setState(getDrawableState());
966 }
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700967 }
968 }
969 }
970
971 /**
972 * Should only be called if we've already verified that mProgressDrawable
973 * and mProgressTintInfo are non-null.
974 */
975 private void applyProgressBackgroundTint() {
976 if (mProgressTintInfo.mHasProgressBackgroundTint
977 || mProgressTintInfo.mHasProgressBackgroundTintMode) {
978 final Drawable target = getTintTarget(R.id.background, false);
979 if (target != null) {
980 if (mProgressTintInfo.mHasProgressBackgroundTint) {
981 target.setTintList(mProgressTintInfo.mProgressBackgroundTintList);
982 }
983 if (mProgressTintInfo.mHasProgressBackgroundTintMode) {
984 target.setTintMode(mProgressTintInfo.mProgressBackgroundTintMode);
985 }
Alan Viveretted5133792014-10-28 14:41:36 -0700986
987 // The drawable (or one of its children) may not have been
988 // stateful before applying the tint, so let's try again.
989 if (target.isStateful()) {
990 target.setState(getDrawableState());
991 }
Alan Viveretteb56f5d22014-09-14 15:48:50 -0700992 }
993 }
994 }
995
996 /**
997 * Should only be called if we've already verified that mProgressDrawable
998 * and mProgressTintInfo are non-null.
999 */
1000 private void applySecondaryProgressTint() {
1001 if (mProgressTintInfo.mHasSecondaryProgressTint
1002 || mProgressTintInfo.mHasSecondaryProgressTintMode) {
1003 final Drawable target = getTintTarget(R.id.secondaryProgress, false);
1004 if (target != null) {
1005 if (mProgressTintInfo.mHasSecondaryProgressTint) {
1006 target.setTintList(mProgressTintInfo.mSecondaryProgressTintList);
1007 }
1008 if (mProgressTintInfo.mHasSecondaryProgressTintMode) {
1009 target.setTintMode(mProgressTintInfo.mSecondaryProgressTintMode);
1010 }
Alan Viveretted5133792014-10-28 14:41:36 -07001011
1012 // The drawable (or one of its children) may not have been
1013 // stateful before applying the tint, so let's try again.
1014 if (target.isStateful()) {
1015 target.setState(getDrawableState());
1016 }
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001017 }
1018 }
1019 }
1020
1021 /**
Alan Viverette91174362014-06-17 14:51:45 -07001022 * Applies a tint to the progress indicator, if one exists, or to the
Alan Viverette91174362014-06-17 14:51:45 -07001023 * entire progress drawable otherwise. Does not modify the current tint
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001024 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
Alan Viverette91174362014-06-17 14:51:45 -07001025 * <p>
1026 * The progress indicator should be specified as a layer with
1027 * id {@link android.R.id#progress} in a {@link LayerDrawable}
1028 * used as the progress drawable.
1029 * <p>
1030 * Subsequent calls to {@link #setProgressDrawable(Drawable)} will
1031 * automatically mutate the drawable and apply the specified tint and
1032 * tint mode using
Alan Viverettea4264452014-07-28 16:02:55 -07001033 * {@link Drawable#setTintList(ColorStateList)}.
Alan Viverette91174362014-06-17 14:51:45 -07001034 *
1035 * @param tint the tint to apply, may be {@code null} to clear tint
1036 *
1037 * @attr ref android.R.styleable#ProgressBar_progressTint
Alan Viverettea4264452014-07-28 16:02:55 -07001038 * @see #getProgressTintList()
1039 * @see Drawable#setTintList(ColorStateList)
Alan Viverette91174362014-06-17 14:51:45 -07001040 */
Jorim Jaggief72a192014-08-26 21:57:46 +02001041 @RemotableViewMethod
Alan Viverettea4264452014-07-28 16:02:55 -07001042 public void setProgressTintList(@Nullable ColorStateList tint) {
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001043 if (mProgressTintInfo == null) {
1044 mProgressTintInfo = new ProgressTintInfo();
1045 }
1046 mProgressTintInfo.mProgressTintList = tint;
1047 mProgressTintInfo.mHasProgressTint = true;
Alan Viverette4f64c042014-07-21 17:49:13 -07001048
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001049 if (mProgressDrawable != null) {
1050 applyPrimaryProgressTint();
1051 }
Alan Viverette91174362014-06-17 14:51:45 -07001052 }
1053
1054 /**
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001055 * Returns the tint applied to the progress drawable, if specified.
1056 *
Alan Viverette91174362014-06-17 14:51:45 -07001057 * @return the tint applied to the progress drawable
1058 * @attr ref android.R.styleable#ProgressBar_progressTint
Alan Viverettea4264452014-07-28 16:02:55 -07001059 * @see #setProgressTintList(ColorStateList)
Alan Viverette91174362014-06-17 14:51:45 -07001060 */
Ashley Rose55f9f922019-01-28 19:29:36 -05001061 @InspectableProperty(name = "progressTint")
Alan Viverette91174362014-06-17 14:51:45 -07001062 @Nullable
Alan Viverettea4264452014-07-28 16:02:55 -07001063 public ColorStateList getProgressTintList() {
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001064 return mProgressTintInfo != null ? mProgressTintInfo.mProgressTintList : null;
Alan Viverette91174362014-06-17 14:51:45 -07001065 }
1066
1067 /**
1068 * Specifies the blending mode used to apply the tint specified by
Alan Viverettea4264452014-07-28 16:02:55 -07001069 * {@link #setProgressTintList(ColorStateList)}} to the progress
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001070 * indicator. The default mode is {@link PorterDuff.Mode#SRC_IN}.
Alan Viverette91174362014-06-17 14:51:45 -07001071 *
1072 * @param tintMode the blending mode used to apply the tint, may be
1073 * {@code null} to clear tint
1074 * @attr ref android.R.styleable#ProgressBar_progressTintMode
Alan Viverette4f64c042014-07-21 17:49:13 -07001075 * @see #getProgressTintMode()
Alan Viverettea4264452014-07-28 16:02:55 -07001076 * @see Drawable#setTintMode(PorterDuff.Mode)
Alan Viverette91174362014-06-17 14:51:45 -07001077 */
1078 public void setProgressTintMode(@Nullable PorterDuff.Mode tintMode) {
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001079 if (mProgressTintInfo == null) {
1080 mProgressTintInfo = new ProgressTintInfo();
1081 }
1082 mProgressTintInfo.mProgressTintMode = tintMode;
1083 mProgressTintInfo.mHasProgressTintMode = true;
Alan Viverette4f64c042014-07-21 17:49:13 -07001084
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001085 if (mProgressDrawable != null) {
1086 applyPrimaryProgressTint();
1087 }
Alan Viverette91174362014-06-17 14:51:45 -07001088 }
1089
1090 /**
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001091 * Returns the blending mode used to apply the tint to the progress
1092 * drawable, if specified.
1093 *
1094 * @return the blending mode used to apply the tint to the progress
1095 * drawable
Alan Viverette91174362014-06-17 14:51:45 -07001096 * @attr ref android.R.styleable#ProgressBar_progressTintMode
Alan Viverette4f64c042014-07-21 17:49:13 -07001097 * @see #setProgressTintMode(PorterDuff.Mode)
Alan Viverette91174362014-06-17 14:51:45 -07001098 */
Ashley Rose55f9f922019-01-28 19:29:36 -05001099 @InspectableProperty
Alan Viverette91174362014-06-17 14:51:45 -07001100 @Nullable
1101 public PorterDuff.Mode getProgressTintMode() {
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001102 return mProgressTintInfo != null ? mProgressTintInfo.mProgressTintMode : null;
Alan Viverette91174362014-06-17 14:51:45 -07001103 }
1104
1105 /**
Alan Viverette91174362014-06-17 14:51:45 -07001106 * Applies a tint to the progress background, if one exists. Does not
1107 * modify the current tint mode, which is
1108 * {@link PorterDuff.Mode#SRC_ATOP} by default.
1109 * <p>
1110 * The progress background must be specified as a layer with
1111 * id {@link android.R.id#background} in a {@link LayerDrawable}
1112 * used as the progress drawable.
1113 * <p>
1114 * Subsequent calls to {@link #setProgressDrawable(Drawable)} where the
1115 * drawable contains a progress background will automatically mutate the
1116 * drawable and apply the specified tint and tint mode using
Alan Viverettea4264452014-07-28 16:02:55 -07001117 * {@link Drawable#setTintList(ColorStateList)}.
Alan Viverette91174362014-06-17 14:51:45 -07001118 *
1119 * @param tint the tint to apply, may be {@code null} to clear tint
1120 *
1121 * @attr ref android.R.styleable#ProgressBar_progressBackgroundTint
Alan Viverettea4264452014-07-28 16:02:55 -07001122 * @see #getProgressBackgroundTintList()
1123 * @see Drawable#setTintList(ColorStateList)
Alan Viverette91174362014-06-17 14:51:45 -07001124 */
Jorim Jaggief72a192014-08-26 21:57:46 +02001125 @RemotableViewMethod
Alan Viverettea4264452014-07-28 16:02:55 -07001126 public void setProgressBackgroundTintList(@Nullable ColorStateList tint) {
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001127 if (mProgressTintInfo == null) {
1128 mProgressTintInfo = new ProgressTintInfo();
1129 }
1130 mProgressTintInfo.mProgressBackgroundTintList = tint;
1131 mProgressTintInfo.mHasProgressBackgroundTint = true;
Alan Viverette4f64c042014-07-21 17:49:13 -07001132
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001133 if (mProgressDrawable != null) {
1134 applyProgressBackgroundTint();
1135 }
Alan Viverette91174362014-06-17 14:51:45 -07001136 }
1137
1138 /**
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001139 * Returns the tint applied to the progress background, if specified.
1140 *
Alan Viverette91174362014-06-17 14:51:45 -07001141 * @return the tint applied to the progress background
1142 * @attr ref android.R.styleable#ProgressBar_progressBackgroundTint
Alan Viverettea4264452014-07-28 16:02:55 -07001143 * @see #setProgressBackgroundTintList(ColorStateList)
Alan Viverette91174362014-06-17 14:51:45 -07001144 */
Ashley Rose55f9f922019-01-28 19:29:36 -05001145 @InspectableProperty(name = "progressBackgroundTint")
Alan Viverette91174362014-06-17 14:51:45 -07001146 @Nullable
Alan Viverettea4264452014-07-28 16:02:55 -07001147 public ColorStateList getProgressBackgroundTintList() {
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001148 return mProgressTintInfo != null ? mProgressTintInfo.mProgressBackgroundTintList : null;
Alan Viverette91174362014-06-17 14:51:45 -07001149 }
1150
1151 /**
1152 * Specifies the blending mode used to apply the tint specified by
Alan Viverettea4264452014-07-28 16:02:55 -07001153 * {@link #setProgressBackgroundTintList(ColorStateList)}} to the progress
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001154 * background. The default mode is {@link PorterDuff.Mode#SRC_IN}.
Alan Viverette91174362014-06-17 14:51:45 -07001155 *
1156 * @param tintMode the blending mode used to apply the tint, may be
1157 * {@code null} to clear tint
1158 * @attr ref android.R.styleable#ProgressBar_progressBackgroundTintMode
Alan Viverettea4264452014-07-28 16:02:55 -07001159 * @see #setProgressBackgroundTintList(ColorStateList)
1160 * @see Drawable#setTintMode(PorterDuff.Mode)
Alan Viverette91174362014-06-17 14:51:45 -07001161 */
1162 public void setProgressBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001163 if (mProgressTintInfo == null) {
1164 mProgressTintInfo = new ProgressTintInfo();
1165 }
1166 mProgressTintInfo.mProgressBackgroundTintMode = tintMode;
1167 mProgressTintInfo.mHasProgressBackgroundTintMode = true;
Alan Viverette4f64c042014-07-21 17:49:13 -07001168
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001169 if (mProgressDrawable != null) {
1170 applyProgressBackgroundTint();
1171 }
Alan Viverette91174362014-06-17 14:51:45 -07001172 }
1173
1174 /**
1175 * @return the blending mode used to apply the tint to the progress
1176 * background
1177 * @attr ref android.R.styleable#ProgressBar_progressBackgroundTintMode
Alan Viverette4f64c042014-07-21 17:49:13 -07001178 * @see #setProgressBackgroundTintMode(PorterDuff.Mode)
Alan Viverette91174362014-06-17 14:51:45 -07001179 */
Ashley Rose55f9f922019-01-28 19:29:36 -05001180 @InspectableProperty
Alan Viverette91174362014-06-17 14:51:45 -07001181 @Nullable
1182 public PorterDuff.Mode getProgressBackgroundTintMode() {
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001183 return mProgressTintInfo != null ? mProgressTintInfo.mProgressBackgroundTintMode : null;
Alan Viverette91174362014-06-17 14:51:45 -07001184 }
1185
1186 /**
1187 * Applies a tint to the secondary progress indicator, if one exists.
Alan Viverette91174362014-06-17 14:51:45 -07001188 * Does not modify the current tint mode, which is
1189 * {@link PorterDuff.Mode#SRC_ATOP} by default.
1190 * <p>
1191 * The secondary progress indicator must be specified as a layer with
1192 * id {@link android.R.id#secondaryProgress} in a {@link LayerDrawable}
1193 * used as the progress drawable.
1194 * <p>
1195 * Subsequent calls to {@link #setProgressDrawable(Drawable)} where the
1196 * drawable contains a secondary progress indicator will automatically
1197 * mutate the drawable and apply the specified tint and tint mode using
Alan Viverettea4264452014-07-28 16:02:55 -07001198 * {@link Drawable#setTintList(ColorStateList)}.
Alan Viverette91174362014-06-17 14:51:45 -07001199 *
1200 * @param tint the tint to apply, may be {@code null} to clear tint
1201 *
1202 * @attr ref android.R.styleable#ProgressBar_secondaryProgressTint
Alan Viverettea4264452014-07-28 16:02:55 -07001203 * @see #getSecondaryProgressTintList()
1204 * @see Drawable#setTintList(ColorStateList)
Alan Viverette91174362014-06-17 14:51:45 -07001205 */
Alan Viverettea4264452014-07-28 16:02:55 -07001206 public void setSecondaryProgressTintList(@Nullable ColorStateList tint) {
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001207 if (mProgressTintInfo == null) {
1208 mProgressTintInfo = new ProgressTintInfo();
1209 }
1210 mProgressTintInfo.mSecondaryProgressTintList = tint;
1211 mProgressTintInfo.mHasSecondaryProgressTint = true;
Alan Viverette4f64c042014-07-21 17:49:13 -07001212
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001213 if (mProgressDrawable != null) {
1214 applySecondaryProgressTint();
1215 }
Alan Viverette91174362014-06-17 14:51:45 -07001216 }
1217
1218 /**
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001219 * Returns the tint applied to the secondary progress drawable, if
1220 * specified.
1221 *
Alan Viverette91174362014-06-17 14:51:45 -07001222 * @return the tint applied to the secondary progress drawable
1223 * @attr ref android.R.styleable#ProgressBar_secondaryProgressTint
Alan Viverettea4264452014-07-28 16:02:55 -07001224 * @see #setSecondaryProgressTintList(ColorStateList)
Alan Viverette91174362014-06-17 14:51:45 -07001225 */
Ashley Rose55f9f922019-01-28 19:29:36 -05001226 @InspectableProperty(name = "secondaryProgressTint")
Alan Viverette91174362014-06-17 14:51:45 -07001227 @Nullable
Alan Viverettea4264452014-07-28 16:02:55 -07001228 public ColorStateList getSecondaryProgressTintList() {
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001229 return mProgressTintInfo != null ? mProgressTintInfo.mSecondaryProgressTintList : null;
Alan Viverette91174362014-06-17 14:51:45 -07001230 }
1231
1232 /**
1233 * Specifies the blending mode used to apply the tint specified by
Alan Viverettea4264452014-07-28 16:02:55 -07001234 * {@link #setSecondaryProgressTintList(ColorStateList)}} to the secondary
Alan Viverette91174362014-06-17 14:51:45 -07001235 * progress indicator. The default mode is
1236 * {@link PorterDuff.Mode#SRC_ATOP}.
1237 *
1238 * @param tintMode the blending mode used to apply the tint, may be
1239 * {@code null} to clear tint
1240 * @attr ref android.R.styleable#ProgressBar_secondaryProgressTintMode
Alan Viverettea4264452014-07-28 16:02:55 -07001241 * @see #setSecondaryProgressTintList(ColorStateList)
1242 * @see Drawable#setTintMode(PorterDuff.Mode)
Alan Viverette91174362014-06-17 14:51:45 -07001243 */
1244 public void setSecondaryProgressTintMode(@Nullable PorterDuff.Mode tintMode) {
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001245 if (mProgressTintInfo == null) {
1246 mProgressTintInfo = new ProgressTintInfo();
1247 }
1248 mProgressTintInfo.mSecondaryProgressTintMode = tintMode;
1249 mProgressTintInfo.mHasSecondaryProgressTintMode = true;
Alan Viverette4f64c042014-07-21 17:49:13 -07001250
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001251 if (mProgressDrawable != null) {
1252 applySecondaryProgressTint();
1253 }
Alan Viverette91174362014-06-17 14:51:45 -07001254 }
1255
1256 /**
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001257 * Returns the blending mode used to apply the tint to the secondary
1258 * progress drawable, if specified.
1259 *
Alan Viverette91174362014-06-17 14:51:45 -07001260 * @return the blending mode used to apply the tint to the secondary
1261 * progress drawable
1262 * @attr ref android.R.styleable#ProgressBar_secondaryProgressTintMode
Alan Viverette4f64c042014-07-21 17:49:13 -07001263 * @see #setSecondaryProgressTintMode(PorterDuff.Mode)
Alan Viverette91174362014-06-17 14:51:45 -07001264 */
Ashley Rose55f9f922019-01-28 19:29:36 -05001265 @InspectableProperty
Alan Viverette91174362014-06-17 14:51:45 -07001266 @Nullable
1267 public PorterDuff.Mode getSecondaryProgressTintMode() {
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001268 return mProgressTintInfo != null ? mProgressTintInfo.mSecondaryProgressTintMode : null;
Alan Viverette91174362014-06-17 14:51:45 -07001269 }
1270
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001271 /**
1272 * Returns the drawable to which a tint or tint mode should be applied.
1273 *
1274 * @param layerId id of the layer to modify
1275 * @param shouldFallback whether the base drawable should be returned
1276 * if the id does not exist
1277 * @return the drawable to modify
1278 */
1279 @Nullable
1280 private Drawable getTintTarget(int layerId, boolean shouldFallback) {
1281 Drawable layer = null;
1282
Alan Viverette91174362014-06-17 14:51:45 -07001283 final Drawable d = mProgressDrawable;
1284 if (d != null) {
1285 mProgressDrawable = d.mutate();
1286
Alan Viverette91174362014-06-17 14:51:45 -07001287 if (d instanceof LayerDrawable) {
1288 layer = ((LayerDrawable) d).findDrawableByLayerId(layerId);
1289 }
1290
1291 if (shouldFallback && layer == null) {
1292 layer = d;
1293 }
Alan Viverette91174362014-06-17 14:51:45 -07001294 }
Alan Viveretteb56f5d22014-09-14 15:48:50 -07001295
1296 return layer;
Alan Viverette91174362014-06-17 14:51:45 -07001297 }
1298
1299 /**
Alan Viverettee785d022013-09-26 15:21:10 -07001300 * Define the tileable drawable used to draw the progress bar in
1301 * progress mode.
1302 * <p>
1303 * If the drawable is a BitmapDrawable or contains BitmapDrawables, a
1304 * tiled copy will be generated for display as a progress bar.
1305 *
1306 * @param d the new drawable
1307 * @see #getProgressDrawable()
1308 * @see #setIndeterminate(boolean)
1309 */
1310 public void setProgressDrawableTiled(Drawable d) {
1311 if (d != null) {
1312 d = tileify(d, false);
1313 }
1314
1315 setProgressDrawable(d);
1316 }
RoboErik5b071432015-02-11 13:52:05 -08001317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001318 /**
Mihai Popa3df49262019-02-06 12:35:29 +00001319 * Returns the drawable currently used to draw the progress bar. This will be
1320 * either {@link #getProgressDrawable()} or {@link #getIndeterminateDrawable()}
1321 * depending on whether the progress bar is in determinate or indeterminate mode.
1322 *
1323 * @return the drawable currently used to draw the progress bar
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 */
Mihai Popa3df49262019-02-06 12:35:29 +00001325 @Nullable
1326 public Drawable getCurrentDrawable() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327 return mCurrentDrawable;
1328 }
1329
1330 @Override
Alan Viverettef6d87ec2016-03-11 10:09:14 -05001331 protected boolean verifyDrawable(@NonNull Drawable who) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001332 return who == mProgressDrawable || who == mIndeterminateDrawable
1333 || super.verifyDrawable(who);
1334 }
1335
1336 @Override
Dianne Hackborne2136772010-11-04 15:08:59 -07001337 public void jumpDrawablesToCurrentState() {
1338 super.jumpDrawablesToCurrentState();
1339 if (mProgressDrawable != null) mProgressDrawable.jumpToCurrentState();
1340 if (mIndeterminateDrawable != null) mIndeterminateDrawable.jumpToCurrentState();
1341 }
1342
Fabrice Di Meglio4457e852012-09-18 19:23:12 -07001343 /**
1344 * @hide
1345 */
Dianne Hackborne2136772010-11-04 15:08:59 -07001346 @Override
Fabrice Di Meglio0af4b8b2012-06-11 18:30:05 -07001347 public void onResolveDrawables(int layoutDirection) {
1348 final Drawable d = mCurrentDrawable;
1349 if (d != null) {
1350 d.setLayoutDirection(layoutDirection);
1351 }
1352 if (mIndeterminateDrawable != null) {
1353 mIndeterminateDrawable.setLayoutDirection(layoutDirection);
1354 }
1355 if (mProgressDrawable != null) {
1356 mProgressDrawable.setLayoutDirection(layoutDirection);
1357 }
1358 }
1359
1360 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 public void postInvalidate() {
1362 if (!mNoInvalidate) {
1363 super.postInvalidate();
1364 }
1365 }
1366
1367 private class RefreshProgressRunnable implements Runnable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 public void run() {
Adam Powella0506632012-04-10 17:19:20 -07001369 synchronized (ProgressBar.this) {
1370 final int count = mRefreshData.size();
1371 for (int i = 0; i < count; i++) {
1372 final RefreshData rd = mRefreshData.get(i);
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001373 doRefreshProgress(rd.id, rd.progress, rd.fromUser, true, rd.animate);
Adam Powella0506632012-04-10 17:19:20 -07001374 rd.recycle();
1375 }
1376 mRefreshData.clear();
1377 mRefreshIsPosted = false;
1378 }
1379 }
1380 }
1381
Svetoslav Ganovabae2a12012-11-27 16:59:37 -08001382 private static class RefreshData {
1383 private static final int POOL_MAX = 24;
1384 private static final SynchronizedPool<RefreshData> sPool =
1385 new SynchronizedPool<RefreshData>(POOL_MAX);
1386
Adam Powella0506632012-04-10 17:19:20 -07001387 public int id;
Alan Viverette5ce0ec02014-11-25 09:40:54 -08001388 public int progress;
Adam Powella0506632012-04-10 17:19:20 -07001389 public boolean fromUser;
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001390 public boolean animate;
Adam Powella0506632012-04-10 17:19:20 -07001391
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001392 public static RefreshData obtain(int id, int progress, boolean fromUser, boolean animate) {
Adam Powella0506632012-04-10 17:19:20 -07001393 RefreshData rd = sPool.acquire();
Svetoslav Ganovabae2a12012-11-27 16:59:37 -08001394 if (rd == null) {
1395 rd = new RefreshData();
1396 }
Adam Powella0506632012-04-10 17:19:20 -07001397 rd.id = id;
1398 rd.progress = progress;
1399 rd.fromUser = fromUser;
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001400 rd.animate = animate;
Adam Powella0506632012-04-10 17:19:20 -07001401 return rd;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 }
RoboErik5b071432015-02-11 13:52:05 -08001403
Adam Powella0506632012-04-10 17:19:20 -07001404 public void recycle() {
1405 sPool.release(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 }
Svetoslav Ganovabae2a12012-11-27 16:59:37 -08001408
Alan Viverette5ce0ec02014-11-25 09:40:54 -08001409 private synchronized void doRefreshProgress(int id, int progress, boolean fromUser,
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001410 boolean callBackToApp, boolean animate) {
Keyvan Amiri86fb2a22016-09-29 17:53:24 -07001411 int range = mMax - mMin;
1412 final float scale = range > 0 ? (progress - mMin) / (float) range : 0;
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001413 final boolean isPrimary = id == R.id.progress;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001415 if (isPrimary && animate) {
1416 final ObjectAnimator animator = ObjectAnimator.ofFloat(this, VISUAL_PROGRESS, scale);
1417 animator.setAutoCancel(true);
1418 animator.setDuration(PROGRESS_ANIM_DURATION);
1419 animator.setInterpolator(PROGRESS_ANIM_INTERPOLATOR);
1420 animator.start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 } else {
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001422 setVisualProgress(id, scale);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 }
RoboErik5b071432015-02-11 13:52:05 -08001424
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001425 if (isPrimary && callBackToApp) {
RoboErik5b071432015-02-11 13:52:05 -08001426 onProgressRefresh(scale, fromUser, progress);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 }
1428 }
Svetoslav Ganov6518ad72011-03-18 16:19:55 -07001429
RoboErik5b071432015-02-11 13:52:05 -08001430 void onProgressRefresh(float scale, boolean fromUser, int progress) {
Svetoslav Ganov6518ad72011-03-18 16:19:55 -07001431 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
1432 scheduleAccessibilityEventSender();
1433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 }
1435
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001436 /**
1437 * Sets the visual state of a progress indicator.
1438 *
1439 * @param id the identifier of the progress indicator
1440 * @param progress the visual progress in the range [0...1]
1441 */
1442 private void setVisualProgress(int id, float progress) {
1443 mVisualProgress = progress;
1444
1445 Drawable d = mCurrentDrawable;
1446
1447 if (d instanceof LayerDrawable) {
1448 d = ((LayerDrawable) d).findDrawableByLayerId(id);
Alan Viverette4d59b812016-04-12 17:17:55 -04001449 if (d == null) {
1450 // If we can't find the requested layer, fall back to setting
1451 // the level of the entire drawable. This will break if
1452 // progress is set on multiple elements, but the theme-default
1453 // drawable will always have all layer IDs present.
1454 d = mCurrentDrawable;
1455 }
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001456 }
1457
1458 if (d != null) {
1459 final int level = (int) (progress * MAX_LEVEL);
1460 d.setLevel(level);
1461 } else {
1462 invalidate();
1463 }
1464
1465 onVisualProgressChanged(id, progress);
1466 }
1467
1468 /**
1469 * Called when the visual state of a progress indicator changes.
1470 *
1471 * @param id the identifier of the progress indicator
1472 * @param progress the visual progress in the range [0...1]
1473 */
1474 void onVisualProgressChanged(int id, float progress) {
1475 // Stub method.
1476 }
1477
Mathew Inwood978c6e22018-08-21 15:58:55 +01001478 @UnsupportedAppUsage
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001479 private synchronized void refreshProgress(int id, int progress, boolean fromUser,
1480 boolean animate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 if (mUiThreadId == Thread.currentThread().getId()) {
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001482 doRefreshProgress(id, progress, fromUser, true, animate);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 } else {
Romain Guyab4c4f4f2012-05-06 13:11:24 -07001484 if (mRefreshProgressRunnable == null) {
1485 mRefreshProgressRunnable = new RefreshProgressRunnable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 }
Romain Guyab4c4f4f2012-05-06 13:11:24 -07001487
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001488 final RefreshData rd = RefreshData.obtain(id, progress, fromUser, animate);
Adam Powella0506632012-04-10 17:19:20 -07001489 mRefreshData.add(rd);
1490 if (mAttached && !mRefreshIsPosted) {
Romain Guyab4c4f4f2012-05-06 13:11:24 -07001491 post(mRefreshProgressRunnable);
Adam Powella0506632012-04-10 17:19:20 -07001492 mRefreshIsPosted = true;
1493 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 }
1495 }
RoboErik5b071432015-02-11 13:52:05 -08001496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 /**
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001498 * Sets the current progress to the specified value. Does not do anything
1499 * if the progress bar is in indeterminate mode.
Alan Viverettea1863cf2016-04-20 16:41:17 -04001500 * <p>
1501 * This method will immediately update the visual position of the progress
1502 * indicator. To animate the visual position to the target value, use
1503 * {@link #setProgress(int, boolean)}}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 *
Chet Haase25886a162018-03-28 18:26:53 -07001505 * @param progress the new progress, between {@link #getMin()} and {@link #getMax()}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 *
1507 * @see #setIndeterminate(boolean)
1508 * @see #isIndeterminate()
1509 * @see #getProgress()
RoboErik5b071432015-02-11 13:52:05 -08001510 * @see #incrementProgressBy(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 */
1512 @android.view.RemotableViewMethod
1513 public synchronized void setProgress(int progress) {
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001514 setProgressInternal(progress, false, false);
1515 }
1516
1517 /**
1518 * Sets the current progress to the specified value, optionally animating
Alan Viverettea1863cf2016-04-20 16:41:17 -04001519 * the visual position between the current and target values.
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001520 * <p>
1521 * Animation does not affect the result of {@link #getProgress()}, which
1522 * will return the target value immediately after this method is called.
1523 *
Chet Haase25886a162018-03-28 18:26:53 -07001524 * @param progress the new progress value, between {@link #getMin()} and {@link #getMax()}
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001525 * @param animate {@code true} to animate between the current and target
1526 * values or {@code false} to not animate
1527 */
1528 public void setProgress(int progress, boolean animate) {
1529 setProgressInternal(progress, false, animate);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 }
RoboErik5b071432015-02-11 13:52:05 -08001531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 @android.view.RemotableViewMethod
Mathew Inwood978c6e22018-08-21 15:58:55 +01001533 @UnsupportedAppUsage
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001534 synchronized boolean setProgressInternal(int progress, boolean fromUser, boolean animate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 if (mIndeterminate) {
Alan Viverette12a44912015-04-16 13:06:00 -07001536 // Not applicable.
1537 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 }
1539
Keyvan Amiri86fb2a22016-09-29 17:53:24 -07001540 progress = MathUtils.constrain(progress, mMin, mMax);
Alan Viverette12a44912015-04-16 13:06:00 -07001541
1542 if (progress == mProgress) {
1543 // No change from current.
1544 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 }
1546
Alan Viverette12a44912015-04-16 13:06:00 -07001547 mProgress = progress;
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001548 refreshProgress(R.id.progress, mProgress, fromUser, animate);
Alan Viverette12a44912015-04-16 13:06:00 -07001549 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 }
1551
1552 /**
1553 * <p>
1554 * Set the current secondary progress to the specified value. Does not do
1555 * anything if the progress bar is in indeterminate mode.
1556 * </p>
RoboErik5b071432015-02-11 13:52:05 -08001557 *
Chet Haase25886a162018-03-28 18:26:53 -07001558 * @param secondaryProgress the new secondary progress, between {@link #getMin()} and
1559 * {@link #getMax()}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 * @see #setIndeterminate(boolean)
1561 * @see #isIndeterminate()
1562 * @see #getSecondaryProgress()
1563 * @see #incrementSecondaryProgressBy(int)
1564 */
1565 @android.view.RemotableViewMethod
1566 public synchronized void setSecondaryProgress(int secondaryProgress) {
1567 if (mIndeterminate) {
1568 return;
1569 }
1570
Keyvan Amiri86fb2a22016-09-29 17:53:24 -07001571 if (secondaryProgress < mMin) {
1572 secondaryProgress = mMin;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 }
1574
1575 if (secondaryProgress > mMax) {
1576 secondaryProgress = mMax;
1577 }
1578
1579 if (secondaryProgress != mSecondaryProgress) {
1580 mSecondaryProgress = secondaryProgress;
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001581 refreshProgress(R.id.secondaryProgress, mSecondaryProgress, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 }
1583 }
1584
1585 /**
1586 * <p>Get the progress bar's current level of progress. Return 0 when the
1587 * progress bar is in indeterminate mode.</p>
1588 *
Chet Haase25886a162018-03-28 18:26:53 -07001589 * @return the current progress, between {@link #getMin()} and {@link #getMax()}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001590 *
1591 * @see #setIndeterminate(boolean)
1592 * @see #isIndeterminate()
1593 * @see #setProgress(int)
1594 * @see #setMax(int)
1595 * @see #getMax()
1596 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07001597 @ViewDebug.ExportedProperty(category = "progress")
Ashley Rose55f9f922019-01-28 19:29:36 -05001598 @InspectableProperty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 public synchronized int getProgress() {
1600 return mIndeterminate ? 0 : mProgress;
1601 }
1602
1603 /**
1604 * <p>Get the progress bar's current level of secondary progress. Return 0 when the
1605 * progress bar is in indeterminate mode.</p>
1606 *
Chet Haase25886a162018-03-28 18:26:53 -07001607 * @return the current secondary progress, between {@link #getMin()} and {@link #getMax()}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 *
1609 * @see #setIndeterminate(boolean)
1610 * @see #isIndeterminate()
1611 * @see #setSecondaryProgress(int)
1612 * @see #setMax(int)
1613 * @see #getMax()
1614 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07001615 @ViewDebug.ExportedProperty(category = "progress")
Ashley Rose55f9f922019-01-28 19:29:36 -05001616 @InspectableProperty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 public synchronized int getSecondaryProgress() {
1618 return mIndeterminate ? 0 : mSecondaryProgress;
1619 }
1620
1621 /**
Keyvan Amiri86fb2a22016-09-29 17:53:24 -07001622 * <p>Return the lower limit of this progress bar's range.</p>
1623 *
1624 * @return a positive integer
1625 *
1626 * @see #setMin(int)
1627 * @see #getProgress()
1628 * @see #getSecondaryProgress()
1629 */
1630 @ViewDebug.ExportedProperty(category = "progress")
Ashley Rose55f9f922019-01-28 19:29:36 -05001631 @InspectableProperty
Keyvan Amiri86fb2a22016-09-29 17:53:24 -07001632 public synchronized int getMin() {
1633 return mMin;
1634 }
1635
1636 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 * <p>Return the upper limit of this progress bar's range.</p>
1638 *
1639 * @return a positive integer
1640 *
1641 * @see #setMax(int)
1642 * @see #getProgress()
1643 * @see #getSecondaryProgress()
1644 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07001645 @ViewDebug.ExportedProperty(category = "progress")
Ashley Rose55f9f922019-01-28 19:29:36 -05001646 @InspectableProperty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 public synchronized int getMax() {
1648 return mMax;
1649 }
1650
1651 /**
Keyvan Amiri86fb2a22016-09-29 17:53:24 -07001652 * <p>Set the lower range of the progress bar to <tt>min</tt>.</p>
1653 *
1654 * @param min the lower range of this progress bar
1655 *
1656 * @see #getMin()
1657 * @see #setProgress(int)
1658 * @see #setSecondaryProgress(int)
1659 */
1660 @android.view.RemotableViewMethod
1661 public synchronized void setMin(int min) {
1662 if (mMaxInitialized) {
1663 if (min > mMax) {
1664 min = mMax;
1665 }
1666 }
1667 mMinInitialized = true;
1668 if (mMaxInitialized && min != mMin) {
1669 mMin = min;
1670 postInvalidate();
1671
1672 if (mProgress < min) {
1673 mProgress = min;
1674 }
1675 refreshProgress(R.id.progress, mProgress, false, false);
1676 } else {
1677 mMin = min;
1678 }
1679 }
1680
1681 /**
1682 * <p>Set the upper range of the progress bar <tt>max</tt>.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 *
1684 * @param max the upper range of this progress bar
1685 *
1686 * @see #getMax()
RoboErik5b071432015-02-11 13:52:05 -08001687 * @see #setProgress(int)
1688 * @see #setSecondaryProgress(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001689 */
1690 @android.view.RemotableViewMethod
1691 public synchronized void setMax(int max) {
Keyvan Amiri86fb2a22016-09-29 17:53:24 -07001692 if (mMinInitialized) {
1693 if (max < mMin) {
1694 max = mMin;
1695 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001696 }
Keyvan Amiri86fb2a22016-09-29 17:53:24 -07001697 mMaxInitialized = true;
1698 if (mMinInitialized && max != mMax) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 mMax = max;
1700 postInvalidate();
1701
1702 if (mProgress > max) {
1703 mProgress = max;
1704 }
Alan Viverettea64ed3b2015-09-23 10:01:45 -04001705 refreshProgress(R.id.progress, mProgress, false, false);
Keyvan Amiri86fb2a22016-09-29 17:53:24 -07001706 } else {
1707 mMax = max;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 }
1709 }
RoboErik5b071432015-02-11 13:52:05 -08001710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 /**
1712 * <p>Increase the progress bar's progress by the specified amount.</p>
1713 *
1714 * @param diff the amount by which the progress must be increased
1715 *
RoboErik5b071432015-02-11 13:52:05 -08001716 * @see #setProgress(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717 */
1718 public synchronized final void incrementProgressBy(int diff) {
1719 setProgress(mProgress + diff);
1720 }
1721
1722 /**
1723 * <p>Increase the progress bar's secondary progress by the specified amount.</p>
1724 *
1725 * @param diff the amount by which the secondary progress must be increased
1726 *
RoboErik5b071432015-02-11 13:52:05 -08001727 * @see #setSecondaryProgress(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 */
1729 public synchronized final void incrementSecondaryProgressBy(int diff) {
1730 setSecondaryProgress(mSecondaryProgress + diff);
1731 }
1732
1733 /**
1734 * <p>Start the indeterminate progress animation.</p>
1735 */
Mathew Inwood978c6e22018-08-21 15:58:55 +01001736 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001737 void startAnimation() {
Adam Powellc1bba9b2016-03-03 16:51:17 -08001738 if (getVisibility() != VISIBLE || getWindowVisibility() != VISIBLE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 return;
1740 }
1741
Jean-Baptiste Querucf4550c2009-07-21 11:16:54 -07001742 if (mIndeterminateDrawable instanceof Animatable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743 mShouldStartAnimationDrawable = true;
Romain Guyab4c4f4f2012-05-06 13:11:24 -07001744 mHasAnimation = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 } else {
Romain Guyab4c4f4f2012-05-06 13:11:24 -07001746 mHasAnimation = true;
1747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 if (mInterpolator == null) {
1749 mInterpolator = new LinearInterpolator();
1750 }
RoboErik5b071432015-02-11 13:52:05 -08001751
Romain Guyab4c4f4f2012-05-06 13:11:24 -07001752 if (mTransformation == null) {
1753 mTransformation = new Transformation();
1754 } else {
1755 mTransformation.clear();
1756 }
RoboErik5b071432015-02-11 13:52:05 -08001757
Romain Guyab4c4f4f2012-05-06 13:11:24 -07001758 if (mAnimation == null) {
1759 mAnimation = new AlphaAnimation(0.0f, 1.0f);
1760 } else {
1761 mAnimation.reset();
1762 }
1763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764 mAnimation.setRepeatMode(mBehavior);
1765 mAnimation.setRepeatCount(Animation.INFINITE);
1766 mAnimation.setDuration(mDuration);
1767 mAnimation.setInterpolator(mInterpolator);
1768 mAnimation.setStartTime(Animation.START_ON_FIRST_FRAME);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 }
Evan Charlton08e14732010-06-07 10:38:53 -07001770 postInvalidate();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 }
1772
1773 /**
1774 * <p>Stop the indeterminate progress animation.</p>
1775 */
Mathew Inwood978c6e22018-08-21 15:58:55 +01001776 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 void stopAnimation() {
Romain Guyab4c4f4f2012-05-06 13:11:24 -07001778 mHasAnimation = false;
Jean-Baptiste Querucf4550c2009-07-21 11:16:54 -07001779 if (mIndeterminateDrawable instanceof Animatable) {
1780 ((Animatable) mIndeterminateDrawable).stop();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 mShouldStartAnimationDrawable = false;
1782 }
Evan Charlton08e14732010-06-07 10:38:53 -07001783 postInvalidate();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 }
1785
1786 /**
1787 * Sets the acceleration curve for the indeterminate animation.
shepshapard3b070452019-02-08 16:54:55 -08001788 *
1789 * <p>The interpolator is loaded as a resource from the specified context. Defaults to a linear
1790 * interpolation.
1791 *
1792 * <p>The interpolator only affects the indeterminate animation if the
1793 * {@link #setIndeterminateDrawable(Drawable) supplied indeterminate drawable} does not
1794 * implement {@link Animatable}.
1795 *
1796 * <p>This call must be made before the indeterminate animation starts for it to have an affect.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 *
1798 * @param context The application environment
1799 * @param resID The resource identifier of the interpolator to load
shepshapard3b070452019-02-08 16:54:55 -08001800 * @attr ref android.R.styleable#ProgressBar_interpolator
1801 * @see #setInterpolator(Interpolator)
1802 * @see #getInterpolator()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 */
Tor Norbye7b9c9122013-05-30 16:48:33 -07001804 public void setInterpolator(Context context, @InterpolatorRes int resID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 setInterpolator(AnimationUtils.loadInterpolator(context, resID));
1806 }
1807
1808 /**
1809 * Sets the acceleration curve for the indeterminate animation.
1810 * Defaults to a linear interpolation.
1811 *
shepshapard3b070452019-02-08 16:54:55 -08001812 * <p>The interpolator only affects the indeterminate animation if the
1813 * {@link #setIndeterminateDrawable(Drawable) supplied indeterminate drawable} does not
1814 * implement {@link Animatable}.
1815 *
1816 * <p>This call must be made before the indeterminate animation starts for it to have
1817 * an affect.
1818 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001819 * @param interpolator The interpolator which defines the acceleration curve
shepshapard3b070452019-02-08 16:54:55 -08001820 * @attr ref android.R.styleable#ProgressBar_interpolator
1821 * @see #setInterpolator(Context, int)
1822 * @see #getInterpolator()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001823 */
1824 public void setInterpolator(Interpolator interpolator) {
1825 mInterpolator = interpolator;
1826 }
1827
1828 /**
1829 * Gets the acceleration curve type for the indeterminate animation.
1830 *
1831 * @return the {@link Interpolator} associated to this animation
shepshapard3b070452019-02-08 16:54:55 -08001832 * @attr ref android.R.styleable#ProgressBar_interpolator
1833 * @see #setInterpolator(Context, int)
1834 * @see #setInterpolator(Interpolator)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 */
Ashley Rose55f9f922019-01-28 19:29:36 -05001836 @InspectableProperty
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 public Interpolator getInterpolator() {
1838 return mInterpolator;
1839 }
1840
1841 @Override
Adam Powell9c146bf2016-03-15 17:35:00 -07001842 public void onVisibilityAggregated(boolean isVisible) {
1843 super.onVisibilityAggregated(isVisible);
Adam Powell41d96902016-03-15 14:43:19 -07001844
Adam Powell41d96902016-03-15 14:43:19 -07001845 if (isVisible != mAggregatedIsVisible) {
1846 mAggregatedIsVisible = isVisible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847
1848 if (mIndeterminate) {
1849 // let's be nice with the UI thread
Adam Powell41d96902016-03-15 14:43:19 -07001850 if (isVisible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001851 startAnimation();
Adam Powell41d96902016-03-15 14:43:19 -07001852 } else {
1853 stopAnimation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854 }
1855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856
Adam Powell41d96902016-03-15 14:43:19 -07001857 if (mCurrentDrawable != null) {
1858 mCurrentDrawable.setVisible(isVisible, false);
Romain Guya05e8a52010-02-25 14:32:39 -08001859 }
1860 }
1861 }
1862
1863 @Override
Alan Viverettef6d87ec2016-03-11 10:09:14 -05001864 public void invalidateDrawable(@NonNull Drawable dr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001865 if (!mInDrawing) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07001866 if (verifyDrawable(dr)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 final Rect dirty = dr.getBounds();
Chris Craik7546a4b2013-10-30 19:49:37 -07001868 final int scrollX = mScrollX + mPaddingLeft;
1869 final int scrollY = mScrollY + mPaddingTop;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870
Chris Craik7546a4b2013-10-30 19:49:37 -07001871 invalidate(dirty.left + scrollX, dirty.top + scrollY,
1872 dirty.right + scrollX, dirty.bottom + scrollY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873 } else {
1874 super.invalidateDrawable(dr);
1875 }
1876 }
1877 }
1878
1879 @Override
1880 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Joe Onoratoaa072632010-12-08 15:31:28 -08001881 updateDrawableBounds(w, h);
1882 }
1883
1884 private void updateDrawableBounds(int w, int h) {
Adam Powell6322af52012-08-08 15:59:12 -07001885 // onDraw will translate the canvas so we draw starting at 0,0.
1886 // Subtract out padding for the purposes of the calculations below.
1887 w -= mPaddingRight + mPaddingLeft;
1888 h -= mPaddingTop + mPaddingBottom;
1889
1890 int right = w;
1891 int bottom = h;
Adam Powella1b92c52011-09-02 15:05:15 -07001892 int top = 0;
1893 int left = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894
1895 if (mIndeterminateDrawable != null) {
Chet Haasea79803c2011-09-28 17:51:53 -07001896 // Aspect ratio logic does not apply to AnimationDrawables
1897 if (mOnlyIndeterminate && !(mIndeterminateDrawable instanceof AnimationDrawable)) {
Adam Powella1b92c52011-09-02 15:05:15 -07001898 // Maintain aspect ratio. Certain kinds of animated drawables
1899 // get very confused otherwise.
1900 final int intrinsicWidth = mIndeterminateDrawable.getIntrinsicWidth();
1901 final int intrinsicHeight = mIndeterminateDrawable.getIntrinsicHeight();
1902 final float intrinsicAspect = (float) intrinsicWidth / intrinsicHeight;
1903 final float boundAspect = (float) w / h;
1904 if (intrinsicAspect != boundAspect) {
1905 if (boundAspect > intrinsicAspect) {
1906 // New width is larger. Make it smaller to match height.
1907 final int width = (int) (h * intrinsicAspect);
1908 left = (w - width) / 2;
1909 right = left + width;
1910 } else {
1911 // New height is larger. Make it smaller to match width.
1912 final int height = (int) (w * (1 / intrinsicAspect));
1913 top = (h - height) / 2;
1914 bottom = top + height;
1915 }
1916 }
1917 }
Fabrice Di Meglio2b378cd2013-01-30 16:39:33 -08001918 if (isLayoutRtl() && mMirrorForRtl) {
Fabrice Di Meglio7fb98b32012-09-12 20:04:04 -07001919 int tempLeft = left;
1920 left = w - right;
1921 right = w - tempLeft;
1922 }
Adam Powella1b92c52011-09-02 15:05:15 -07001923 mIndeterminateDrawable.setBounds(left, top, right, bottom);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 }
RoboErik5b071432015-02-11 13:52:05 -08001925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001926 if (mProgressDrawable != null) {
1927 mProgressDrawable.setBounds(0, 0, right, bottom);
1928 }
1929 }
1930
1931 @Override
1932 protected synchronized void onDraw(Canvas canvas) {
1933 super.onDraw(canvas);
1934
Alan Viverette661e6362014-05-12 10:55:37 -07001935 drawTrack(canvas);
1936 }
1937
1938 /**
1939 * Draws the progress bar track.
1940 */
1941 void drawTrack(Canvas canvas) {
1942 final Drawable d = mCurrentDrawable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 if (d != null) {
1944 // Translate canvas so a indeterminate circular progress bar with padding
1945 // rotates properly in its animation
Alan Viverette661e6362014-05-12 10:55:37 -07001946 final int saveCount = canvas.save();
1947
Alan Viverette6a8253f2015-02-23 12:49:47 -08001948 if (isLayoutRtl() && mMirrorForRtl) {
Fabrice Di Meglio7fb98b32012-09-12 20:04:04 -07001949 canvas.translate(getWidth() - mPaddingRight, mPaddingTop);
1950 canvas.scale(-1.0f, 1.0f);
1951 } else {
1952 canvas.translate(mPaddingLeft, mPaddingTop);
1953 }
Alan Viverette661e6362014-05-12 10:55:37 -07001954
1955 final long time = getDrawingTime();
Romain Guyab4c4f4f2012-05-06 13:11:24 -07001956 if (mHasAnimation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001957 mAnimation.getTransformation(time, mTransformation);
Alan Viverette661e6362014-05-12 10:55:37 -07001958 final float scale = mTransformation.getAlpha();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001959 try {
1960 mInDrawing = true;
1961 d.setLevel((int) (scale * MAX_LEVEL));
1962 } finally {
1963 mInDrawing = false;
1964 }
Jeff Brown6cb7b462012-03-05 13:21:17 -08001965 postInvalidateOnAnimation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966 }
Alan Viverette661e6362014-05-12 10:55:37 -07001967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001968 d.draw(canvas);
Alan Viverette661e6362014-05-12 10:55:37 -07001969 canvas.restoreToCount(saveCount);
1970
Jean-Baptiste Querucf4550c2009-07-21 11:16:54 -07001971 if (mShouldStartAnimationDrawable && d instanceof Animatable) {
1972 ((Animatable) d).start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001973 mShouldStartAnimationDrawable = false;
1974 }
1975 }
1976 }
1977
1978 @Override
1979 protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001980 int dw = 0;
1981 int dh = 0;
Alan Viverette6a8253f2015-02-23 12:49:47 -08001982
1983 final Drawable d = mCurrentDrawable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001984 if (d != null) {
1985 dw = Math.max(mMinWidth, Math.min(mMaxWidth, d.getIntrinsicWidth()));
1986 dh = Math.max(mMinHeight, Math.min(mMaxHeight, d.getIntrinsicHeight()));
1987 }
Alan Viverette6a8253f2015-02-23 12:49:47 -08001988
Joe Onoratoaa072632010-12-08 15:31:28 -08001989 updateDrawableState();
Alan Viverette6a8253f2015-02-23 12:49:47 -08001990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001991 dw += mPaddingLeft + mPaddingRight;
1992 dh += mPaddingTop + mPaddingBottom;
1993
Alan Viverette6a8253f2015-02-23 12:49:47 -08001994 final int measuredWidth = resolveSizeAndState(dw, widthMeasureSpec, 0);
1995 final int measuredHeight = resolveSizeAndState(dh, heightMeasureSpec, 0);
1996 setMeasuredDimension(measuredWidth, measuredHeight);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001997 }
RoboErik5b071432015-02-11 13:52:05 -08001998
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001999 @Override
2000 protected void drawableStateChanged() {
2001 super.drawableStateChanged();
Joe Onoratoaa072632010-12-08 15:31:28 -08002002 updateDrawableState();
2003 }
RoboErik5b071432015-02-11 13:52:05 -08002004
Joe Onoratoaa072632010-12-08 15:31:28 -08002005 private void updateDrawableState() {
Alan Viverette6a8253f2015-02-23 12:49:47 -08002006 final int[] state = getDrawableState();
Alan Viverettead0020f2015-09-04 10:10:42 -04002007 boolean changed = false;
RoboErik5b071432015-02-11 13:52:05 -08002008
Alan Viverettead0020f2015-09-04 10:10:42 -04002009 final Drawable progressDrawable = mProgressDrawable;
2010 if (progressDrawable != null && progressDrawable.isStateful()) {
2011 changed |= progressDrawable.setState(state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002012 }
RoboErik5b071432015-02-11 13:52:05 -08002013
Alan Viverettead0020f2015-09-04 10:10:42 -04002014 final Drawable indeterminateDrawable = mIndeterminateDrawable;
2015 if (indeterminateDrawable != null && indeterminateDrawable.isStateful()) {
2016 changed |= indeterminateDrawable.setState(state);
2017 }
2018
2019 if (changed) {
2020 invalidate();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002021 }
2022 }
2023
Alan Viverettecebc6ba2014-06-13 15:52:13 -07002024 @Override
Alan Viverette8de14942014-06-18 18:05:15 -07002025 public void drawableHotspotChanged(float x, float y) {
2026 super.drawableHotspotChanged(x, y);
Alan Viverettecebc6ba2014-06-13 15:52:13 -07002027
2028 if (mProgressDrawable != null) {
2029 mProgressDrawable.setHotspot(x, y);
2030 }
2031
2032 if (mIndeterminateDrawable != null) {
2033 mIndeterminateDrawable.setHotspot(x, y);
2034 }
2035 }
2036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 static class SavedState extends BaseSavedState {
2038 int progress;
2039 int secondaryProgress;
RoboErik5b071432015-02-11 13:52:05 -08002040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002041 /**
2042 * Constructor called from {@link ProgressBar#onSaveInstanceState()}
2043 */
2044 SavedState(Parcelable superState) {
2045 super(superState);
2046 }
RoboErik5b071432015-02-11 13:52:05 -08002047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 /**
2049 * Constructor called from {@link #CREATOR}
2050 */
2051 private SavedState(Parcel in) {
2052 super(in);
2053 progress = in.readInt();
2054 secondaryProgress = in.readInt();
2055 }
2056
2057 @Override
2058 public void writeToParcel(Parcel out, int flags) {
2059 super.writeToParcel(out, flags);
2060 out.writeInt(progress);
2061 out.writeInt(secondaryProgress);
2062 }
2063
2064 public static final Parcelable.Creator<SavedState> CREATOR
2065 = new Parcelable.Creator<SavedState>() {
2066 public SavedState createFromParcel(Parcel in) {
2067 return new SavedState(in);
2068 }
2069
2070 public SavedState[] newArray(int size) {
2071 return new SavedState[size];
2072 }
2073 };
2074 }
2075
2076 @Override
2077 public Parcelable onSaveInstanceState() {
2078 // Force our ancestor class to save its state
2079 Parcelable superState = super.onSaveInstanceState();
2080 SavedState ss = new SavedState(superState);
RoboErik5b071432015-02-11 13:52:05 -08002081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 ss.progress = mProgress;
2083 ss.secondaryProgress = mSecondaryProgress;
RoboErik5b071432015-02-11 13:52:05 -08002084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 return ss;
2086 }
2087
2088 @Override
2089 public void onRestoreInstanceState(Parcelable state) {
2090 SavedState ss = (SavedState) state;
2091 super.onRestoreInstanceState(ss.getSuperState());
RoboErik5b071432015-02-11 13:52:05 -08002092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002093 setProgress(ss.progress);
2094 setSecondaryProgress(ss.secondaryProgress);
2095 }
David Sobreira Marques52a35432010-05-15 16:10:18 -03002096
2097 @Override
2098 protected void onAttachedToWindow() {
2099 super.onAttachedToWindow();
2100 if (mIndeterminate) {
2101 startAnimation();
2102 }
Adam Powella0506632012-04-10 17:19:20 -07002103 if (mRefreshData != null) {
2104 synchronized (this) {
2105 final int count = mRefreshData.size();
2106 for (int i = 0; i < count; i++) {
2107 final RefreshData rd = mRefreshData.get(i);
Alan Viverettea64ed3b2015-09-23 10:01:45 -04002108 doRefreshProgress(rd.id, rd.progress, rd.fromUser, true, rd.animate);
Adam Powella0506632012-04-10 17:19:20 -07002109 rd.recycle();
2110 }
2111 mRefreshData.clear();
2112 }
2113 }
2114 mAttached = true;
David Sobreira Marques52a35432010-05-15 16:10:18 -03002115 }
2116
2117 @Override
2118 protected void onDetachedFromWindow() {
David Sobreira Marques52a35432010-05-15 16:10:18 -03002119 if (mIndeterminate) {
2120 stopAnimation();
2121 }
Adam Powella0506632012-04-10 17:19:20 -07002122 if (mRefreshProgressRunnable != null) {
2123 removeCallbacks(mRefreshProgressRunnable);
Bing Deng24a2bc72012-11-08 13:35:15 +08002124 mRefreshIsPosted = false;
Svetoslav Ganov6518ad72011-03-18 16:19:55 -07002125 }
2126 if (mAccessibilityEventSender != null) {
2127 removeCallbacks(mAccessibilityEventSender);
2128 }
Patrick Dubroyec84c3a2011-01-13 17:55:37 -08002129 // This should come after stopAnimation(), otherwise an invalidate message remains in the
2130 // queue, which can prevent the entire view hierarchy from being GC'ed during a rotation
2131 super.onDetachedFromWindow();
Adam Powella0506632012-04-10 17:19:20 -07002132 mAttached = false;
David Sobreira Marques52a35432010-05-15 16:10:18 -03002133 }
Svetoslav Ganov6518ad72011-03-18 16:19:55 -07002134
2135 @Override
Dianne Hackborna7bb6fb2015-02-03 18:13:40 -08002136 public CharSequence getAccessibilityClassName() {
2137 return ProgressBar.class.getName();
Svetoslav Ganov6518ad72011-03-18 16:19:55 -07002138 }
2139
Alan Viverettea54956a2015-01-07 16:05:02 -08002140 /** @hide */
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -08002141 @Override
Dianne Hackborna7bb6fb2015-02-03 18:13:40 -08002142 public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
2143 super.onInitializeAccessibilityEventInternal(event);
Keyvan Amiri86fb2a22016-09-29 17:53:24 -07002144 event.setItemCount(mMax - mMin);
Dianne Hackborna7bb6fb2015-02-03 18:13:40 -08002145 event.setCurrentItemIndex(mProgress);
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -08002146 }
2147
Maxim Bogatov32e59d52015-04-30 16:57:33 -07002148 /** @hide */
2149 @Override
2150 public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
2151 super.onInitializeAccessibilityNodeInfoInternal(info);
2152
2153 if (!isIndeterminate()) {
2154 AccessibilityNodeInfo.RangeInfo rangeInfo = AccessibilityNodeInfo.RangeInfo.obtain(
Chet Haase25886a162018-03-28 18:26:53 -07002155 AccessibilityNodeInfo.RangeInfo.RANGE_TYPE_INT, getMin(), getMax(),
2156 getProgress());
Maxim Bogatov32e59d52015-04-30 16:57:33 -07002157 info.setRangeInfo(rangeInfo);
2158 }
2159 }
2160
Svetoslav Ganov6518ad72011-03-18 16:19:55 -07002161 /**
2162 * Schedule a command for sending an accessibility event.
2163 * </br>
2164 * Note: A command is used to ensure that accessibility events
2165 * are sent at most one in a given time frame to save
2166 * system resources while the progress changes quickly.
2167 */
2168 private void scheduleAccessibilityEventSender() {
2169 if (mAccessibilityEventSender == null) {
2170 mAccessibilityEventSender = new AccessibilityEventSender();
2171 } else {
2172 removeCallbacks(mAccessibilityEventSender);
2173 }
2174 postDelayed(mAccessibilityEventSender, TIMEOUT_SEND_ACCESSIBILITY_EVENT);
2175 }
2176
Siva Velusamy94a6d152015-05-05 15:07:00 -07002177 /** @hide */
2178 @Override
2179 protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
2180 super.encodeProperties(stream);
2181
2182 stream.addProperty("progress:max", getMax());
2183 stream.addProperty("progress:progress", getProgress());
2184 stream.addProperty("progress:secondaryProgress", getSecondaryProgress());
2185 stream.addProperty("progress:indeterminate", isIndeterminate());
2186 }
2187
Svetoslav Ganov6518ad72011-03-18 16:19:55 -07002188 /**
Chet Haaseb64e777f2016-12-09 07:17:10 -08002189 * Returns whether the ProgressBar is animating or not. This is essentially the same
2190 * as whether the ProgressBar is {@link #isIndeterminate() indeterminate} and visible,
2191 * as indeterminate ProgressBars are always animating, and non-indeterminate
2192 * ProgressBars are not animating.
2193 *
2194 * @return true if the ProgressBar is animating, false otherwise.
2195 */
2196 public boolean isAnimating() {
2197 return isIndeterminate() && getWindowVisibility() == VISIBLE && isShown();
2198 }
2199
2200 /**
Svetoslav Ganov6518ad72011-03-18 16:19:55 -07002201 * Command for sending an accessibility event.
2202 */
2203 private class AccessibilityEventSender implements Runnable {
2204 public void run() {
2205 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
2206 }
2207 }
Alan Viveretteb56f5d22014-09-14 15:48:50 -07002208
2209 private static class ProgressTintInfo {
2210 ColorStateList mIndeterminateTintList;
2211 PorterDuff.Mode mIndeterminateTintMode;
2212 boolean mHasIndeterminateTint;
2213 boolean mHasIndeterminateTintMode;
2214
2215 ColorStateList mProgressTintList;
2216 PorterDuff.Mode mProgressTintMode;
2217 boolean mHasProgressTint;
2218 boolean mHasProgressTintMode;
2219
2220 ColorStateList mProgressBackgroundTintList;
2221 PorterDuff.Mode mProgressBackgroundTintMode;
2222 boolean mHasProgressBackgroundTint;
2223 boolean mHasProgressBackgroundTintMode;
2224
2225 ColorStateList mSecondaryProgressTintList;
2226 PorterDuff.Mode mSecondaryProgressTintMode;
2227 boolean mHasSecondaryProgressTint;
2228 boolean mHasSecondaryProgressTintMode;
2229 }
Alan Viverettea64ed3b2015-09-23 10:01:45 -04002230
2231 /**
2232 * Property wrapper around the visual state of the {@code progress} functionality
2233 * handled by the {@link ProgressBar#setProgress(int, boolean)} method. This does
2234 * not correspond directly to the actual progress -- only the visual state.
2235 */
2236 private final FloatProperty<ProgressBar> VISUAL_PROGRESS =
2237 new FloatProperty<ProgressBar>("visual_progress") {
2238 @Override
2239 public void setValue(ProgressBar object, float value) {
2240 object.setVisualProgress(R.id.progress, value);
2241 object.mVisualProgress = value;
2242 }
2243
2244 @Override
2245 public Float get(ProgressBar object) {
2246 return object.mVisualProgress;
2247 }
2248 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002249}