1 /* 2 * Copyright (C) 2007 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 17 package android.app; 18 19 import android.compat.annotation.UnsupportedAppUsage; 20 import android.content.Context; 21 import android.content.res.TypedArray; 22 import android.graphics.drawable.Drawable; 23 import android.os.Build; 24 import android.os.Bundle; 25 import android.os.Handler; 26 import android.os.Message; 27 import android.text.Spannable; 28 import android.text.SpannableString; 29 import android.text.style.StyleSpan; 30 import android.view.LayoutInflater; 31 import android.view.View; 32 import android.widget.ProgressBar; 33 import android.widget.TextView; 34 35 import com.android.internal.R; 36 37 import java.text.NumberFormat; 38 39 /** 40 * A dialog showing a progress indicator and an optional text message or view. 41 * Only a text message or a view can be used at the same time. 42 * 43 * <p>The dialog can be made cancelable on back key press.</p> 44 * 45 * <p>The progress range is 0 to {@link #getMax() max}.</p> 46 * 47 * @deprecated <code>ProgressDialog</code> is a modal dialog, which prevents the 48 * user from interacting with the app. Instead of using this class, you should 49 * use a progress indicator like {@link android.widget.ProgressBar}, which can 50 * be embedded in your app's UI. Alternatively, you can use a 51 * <a href="/guide/topics/ui/notifiers/notifications.html">notification</a> 52 * to inform the user of the task's progress. 53 */ 54 @Deprecated 55 public class ProgressDialog extends AlertDialog { 56 57 /** 58 * Creates a ProgressDialog with a circular, spinning progress 59 * bar. This is the default. 60 */ 61 public static final int STYLE_SPINNER = 0; 62 63 /** 64 * Creates a ProgressDialog with a horizontal progress bar. 65 */ 66 public static final int STYLE_HORIZONTAL = 1; 67 68 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 69 private ProgressBar mProgress; 70 @UnsupportedAppUsage 71 private TextView mMessageView; 72 73 private int mProgressStyle = STYLE_SPINNER; 74 @UnsupportedAppUsage 75 private TextView mProgressNumber; 76 private String mProgressNumberFormat; 77 private TextView mProgressPercent; 78 private NumberFormat mProgressPercentFormat; 79 80 private int mMax; 81 private int mProgressVal; 82 private int mSecondaryProgressVal; 83 private int mIncrementBy; 84 private int mIncrementSecondaryBy; 85 private Drawable mProgressDrawable; 86 private Drawable mIndeterminateDrawable; 87 private CharSequence mMessage; 88 private boolean mIndeterminate; 89 90 private boolean mHasStarted; 91 private Handler mViewUpdateHandler; 92 93 /** 94 * Creates a Progress dialog. 95 * 96 * @param context the parent context 97 */ ProgressDialog(Context context)98 public ProgressDialog(Context context) { 99 super(context); 100 initFormats(); 101 } 102 103 /** 104 * Creates a Progress dialog. 105 * 106 * @param context the parent context 107 * @param theme the resource ID of the theme against which to inflate 108 * this dialog, or {@code 0} to use the parent 109 * {@code context}'s default alert dialog theme 110 */ ProgressDialog(Context context, int theme)111 public ProgressDialog(Context context, int theme) { 112 super(context, theme); 113 initFormats(); 114 } 115 initFormats()116 private void initFormats() { 117 mProgressNumberFormat = "%1d/%2d"; 118 mProgressPercentFormat = NumberFormat.getPercentInstance(); 119 mProgressPercentFormat.setMaximumFractionDigits(0); 120 } 121 122 /** 123 * Creates and shows a ProgressDialog. 124 * 125 * @param context the parent context 126 * @param title the title text for the dialog's window 127 * @param message the text to be displayed in the dialog 128 * @return the ProgressDialog 129 */ show(Context context, CharSequence title, CharSequence message)130 public static ProgressDialog show(Context context, CharSequence title, 131 CharSequence message) { 132 return show(context, title, message, false); 133 } 134 135 /** 136 * Creates and shows a ProgressDialog. 137 * 138 * @param context the parent context 139 * @param title the title text for the dialog's window 140 * @param message the text to be displayed in the dialog 141 * @param indeterminate true if the dialog should be {@link #setIndeterminate(boolean) 142 * indeterminate}, false otherwise 143 * @return the ProgressDialog 144 */ show(Context context, CharSequence title, CharSequence message, boolean indeterminate)145 public static ProgressDialog show(Context context, CharSequence title, 146 CharSequence message, boolean indeterminate) { 147 return show(context, title, message, indeterminate, false, null); 148 } 149 150 /** 151 * Creates and shows a ProgressDialog. 152 * 153 * @param context the parent context 154 * @param title the title text for the dialog's window 155 * @param message the text to be displayed in the dialog 156 * @param indeterminate true if the dialog should be {@link #setIndeterminate(boolean) 157 * indeterminate}, false otherwise 158 * @param cancelable true if the dialog is {@link #setCancelable(boolean) cancelable}, 159 * false otherwise 160 * @return the ProgressDialog 161 */ show(Context context, CharSequence title, CharSequence message, boolean indeterminate, boolean cancelable)162 public static ProgressDialog show(Context context, CharSequence title, 163 CharSequence message, boolean indeterminate, boolean cancelable) { 164 return show(context, title, message, indeterminate, cancelable, null); 165 } 166 167 /** 168 * Creates and shows a ProgressDialog. 169 * 170 * @param context the parent context 171 * @param title the title text for the dialog's window 172 * @param message the text to be displayed in the dialog 173 * @param indeterminate true if the dialog should be {@link #setIndeterminate(boolean) 174 * indeterminate}, false otherwise 175 * @param cancelable true if the dialog is {@link #setCancelable(boolean) cancelable}, 176 * false otherwise 177 * @param cancelListener the {@link #setOnCancelListener(OnCancelListener) listener} 178 * to be invoked when the dialog is canceled 179 * @return the ProgressDialog 180 */ show(Context context, CharSequence title, CharSequence message, boolean indeterminate, boolean cancelable, OnCancelListener cancelListener)181 public static ProgressDialog show(Context context, CharSequence title, 182 CharSequence message, boolean indeterminate, 183 boolean cancelable, OnCancelListener cancelListener) { 184 ProgressDialog dialog = new ProgressDialog(context); 185 dialog.setTitle(title); 186 dialog.setMessage(message); 187 dialog.setIndeterminate(indeterminate); 188 dialog.setCancelable(cancelable); 189 dialog.setOnCancelListener(cancelListener); 190 dialog.show(); 191 return dialog; 192 } 193 194 @Override onCreate(Bundle savedInstanceState)195 protected void onCreate(Bundle savedInstanceState) { 196 LayoutInflater inflater = LayoutInflater.from(mContext); 197 TypedArray a = mContext.obtainStyledAttributes(null, 198 com.android.internal.R.styleable.AlertDialog, 199 com.android.internal.R.attr.alertDialogStyle, 0); 200 if (mProgressStyle == STYLE_HORIZONTAL) { 201 202 /* Use a separate handler to update the text views as they 203 * must be updated on the same thread that created them. 204 */ 205 mViewUpdateHandler = new Handler() { 206 @Override 207 public void handleMessage(Message msg) { 208 super.handleMessage(msg); 209 210 /* Update the number and percent */ 211 int progress = mProgress.getProgress(); 212 int max = mProgress.getMax(); 213 if (mProgressNumberFormat != null) { 214 String format = mProgressNumberFormat; 215 mProgressNumber.setText(String.format(format, progress, max)); 216 } else { 217 mProgressNumber.setText(""); 218 } 219 if (mProgressPercentFormat != null) { 220 double percent = (double) progress / (double) max; 221 SpannableString tmp = new SpannableString(mProgressPercentFormat.format(percent)); 222 tmp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 223 0, tmp.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 224 mProgressPercent.setText(tmp); 225 } else { 226 mProgressPercent.setText(""); 227 } 228 } 229 }; 230 View view = inflater.inflate(a.getResourceId( 231 com.android.internal.R.styleable.AlertDialog_horizontalProgressLayout, 232 R.layout.alert_dialog_progress), null); 233 mProgress = (ProgressBar) view.findViewById(R.id.progress); 234 mProgressNumber = (TextView) view.findViewById(R.id.progress_number); 235 mProgressPercent = (TextView) view.findViewById(R.id.progress_percent); 236 setView(view); 237 } else { 238 View view = inflater.inflate(a.getResourceId( 239 com.android.internal.R.styleable.AlertDialog_progressLayout, 240 R.layout.progress_dialog), null); 241 mProgress = (ProgressBar) view.findViewById(R.id.progress); 242 mMessageView = (TextView) view.findViewById(R.id.message); 243 setView(view); 244 } 245 a.recycle(); 246 if (mMax > 0) { 247 setMax(mMax); 248 } 249 if (mProgressVal > 0) { 250 setProgress(mProgressVal); 251 } 252 if (mSecondaryProgressVal > 0) { 253 setSecondaryProgress(mSecondaryProgressVal); 254 } 255 if (mIncrementBy > 0) { 256 incrementProgressBy(mIncrementBy); 257 } 258 if (mIncrementSecondaryBy > 0) { 259 incrementSecondaryProgressBy(mIncrementSecondaryBy); 260 } 261 if (mProgressDrawable != null) { 262 setProgressDrawable(mProgressDrawable); 263 } 264 if (mIndeterminateDrawable != null) { 265 setIndeterminateDrawable(mIndeterminateDrawable); 266 } 267 if (mMessage != null) { 268 setMessage(mMessage); 269 } 270 setIndeterminate(mIndeterminate); 271 onProgressChanged(); 272 super.onCreate(savedInstanceState); 273 } 274 275 @Override onStart()276 public void onStart() { 277 super.onStart(); 278 mHasStarted = true; 279 } 280 281 @Override onStop()282 protected void onStop() { 283 super.onStop(); 284 mHasStarted = false; 285 } 286 287 /** 288 * Sets the current progress. 289 * 290 * @param value the current progress, a value between 0 and {@link #getMax()} 291 * 292 * @see ProgressBar#setProgress(int) 293 */ setProgress(int value)294 public void setProgress(int value) { 295 if (mHasStarted) { 296 mProgress.setProgress(value); 297 onProgressChanged(); 298 } else { 299 mProgressVal = value; 300 } 301 } 302 303 /** 304 * Sets the secondary progress. 305 * 306 * @param secondaryProgress the current secondary progress, a value between 0 and 307 * {@link #getMax()} 308 * 309 * @see ProgressBar#setSecondaryProgress(int) 310 */ setSecondaryProgress(int secondaryProgress)311 public void setSecondaryProgress(int secondaryProgress) { 312 if (mProgress != null) { 313 mProgress.setSecondaryProgress(secondaryProgress); 314 onProgressChanged(); 315 } else { 316 mSecondaryProgressVal = secondaryProgress; 317 } 318 } 319 320 /** 321 * Gets the current progress. 322 * 323 * @return the current progress, a value between 0 and {@link #getMax()} 324 */ getProgress()325 public int getProgress() { 326 if (mProgress != null) { 327 return mProgress.getProgress(); 328 } 329 return mProgressVal; 330 } 331 332 /** 333 * Gets the current secondary progress. 334 * 335 * @return the current secondary progress, a value between 0 and {@link #getMax()} 336 */ getSecondaryProgress()337 public int getSecondaryProgress() { 338 if (mProgress != null) { 339 return mProgress.getSecondaryProgress(); 340 } 341 return mSecondaryProgressVal; 342 } 343 344 /** 345 * Gets the maximum allowed progress value. The default value is 100. 346 * 347 * @return the maximum value 348 */ getMax()349 public int getMax() { 350 if (mProgress != null) { 351 return mProgress.getMax(); 352 } 353 return mMax; 354 } 355 356 /** 357 * Sets the maximum allowed progress value. 358 */ setMax(int max)359 public void setMax(int max) { 360 if (mProgress != null) { 361 mProgress.setMax(max); 362 onProgressChanged(); 363 } else { 364 mMax = max; 365 } 366 } 367 368 /** 369 * Increments the current progress value. 370 * 371 * @param diff the amount by which the current progress will be incremented, 372 * up to {@link #getMax()} 373 */ incrementProgressBy(int diff)374 public void incrementProgressBy(int diff) { 375 if (mProgress != null) { 376 mProgress.incrementProgressBy(diff); 377 onProgressChanged(); 378 } else { 379 mIncrementBy += diff; 380 } 381 } 382 383 /** 384 * Increments the current secondary progress value. 385 * 386 * @param diff the amount by which the current secondary progress will be incremented, 387 * up to {@link #getMax()} 388 */ incrementSecondaryProgressBy(int diff)389 public void incrementSecondaryProgressBy(int diff) { 390 if (mProgress != null) { 391 mProgress.incrementSecondaryProgressBy(diff); 392 onProgressChanged(); 393 } else { 394 mIncrementSecondaryBy += diff; 395 } 396 } 397 398 /** 399 * Sets the drawable to be used to display the progress value. 400 * 401 * @param d the drawable to be used 402 * 403 * @see ProgressBar#setProgressDrawable(Drawable) 404 */ setProgressDrawable(Drawable d)405 public void setProgressDrawable(Drawable d) { 406 if (mProgress != null) { 407 mProgress.setProgressDrawable(d); 408 } else { 409 mProgressDrawable = d; 410 } 411 } 412 413 /** 414 * Sets the drawable to be used to display the indeterminate progress value. 415 * 416 * @param d the drawable to be used 417 * 418 * @see ProgressBar#setProgressDrawable(Drawable) 419 * @see #setIndeterminate(boolean) 420 */ setIndeterminateDrawable(Drawable d)421 public void setIndeterminateDrawable(Drawable d) { 422 if (mProgress != null) { 423 mProgress.setIndeterminateDrawable(d); 424 } else { 425 mIndeterminateDrawable = d; 426 } 427 } 428 429 /** 430 * Change the indeterminate mode for this ProgressDialog. In indeterminate 431 * mode, the progress is ignored and the dialog shows an infinite 432 * animation instead. 433 * 434 * <p><strong>Note:</strong> A ProgressDialog with style {@link #STYLE_SPINNER} 435 * is always indeterminate and will ignore this setting.</p> 436 * 437 * @param indeterminate true to enable indeterminate mode, false otherwise 438 * 439 * @see #setProgressStyle(int) 440 */ setIndeterminate(boolean indeterminate)441 public void setIndeterminate(boolean indeterminate) { 442 if (mProgress != null) { 443 mProgress.setIndeterminate(indeterminate); 444 } else { 445 mIndeterminate = indeterminate; 446 } 447 } 448 449 /** 450 * Whether this ProgressDialog is in indeterminate mode. 451 * 452 * @return true if the dialog is in indeterminate mode, false otherwise 453 */ isIndeterminate()454 public boolean isIndeterminate() { 455 if (mProgress != null) { 456 return mProgress.isIndeterminate(); 457 } 458 return mIndeterminate; 459 } 460 461 @Override setMessage(CharSequence message)462 public void setMessage(CharSequence message) { 463 if (mProgress != null) { 464 if (mProgressStyle == STYLE_HORIZONTAL) { 465 super.setMessage(message); 466 } else { 467 mMessageView.setText(message); 468 } 469 } else { 470 mMessage = message; 471 } 472 } 473 474 /** 475 * Sets the style of this ProgressDialog, either {@link #STYLE_SPINNER} or 476 * {@link #STYLE_HORIZONTAL}. The default is {@link #STYLE_SPINNER}. 477 * 478 * <p><strong>Note:</strong> A ProgressDialog with style {@link #STYLE_SPINNER} 479 * is always indeterminate and will ignore the {@link #setIndeterminate(boolean) 480 * indeterminate} setting.</p> 481 * 482 * @param style the style of this ProgressDialog, either {@link #STYLE_SPINNER} or 483 * {@link #STYLE_HORIZONTAL} 484 */ setProgressStyle(int style)485 public void setProgressStyle(int style) { 486 mProgressStyle = style; 487 } 488 489 /** 490 * Change the format of the small text showing current and maximum units 491 * of progress. The default is "%1d/%2d". 492 * Should not be called during the number is progressing. 493 * @param format A string passed to {@link String#format String.format()}; 494 * use "%1d" for the current number and "%2d" for the maximum. If null, 495 * nothing will be shown. 496 */ setProgressNumberFormat(String format)497 public void setProgressNumberFormat(String format) { 498 mProgressNumberFormat = format; 499 onProgressChanged(); 500 } 501 502 /** 503 * Change the format of the small text showing the percentage of progress. 504 * The default is 505 * {@link NumberFormat#getPercentInstance() NumberFormat.getPercentageInstnace().} 506 * Should not be called during the number is progressing. 507 * @param format An instance of a {@link NumberFormat} to generate the 508 * percentage text. If null, nothing will be shown. 509 */ setProgressPercentFormat(NumberFormat format)510 public void setProgressPercentFormat(NumberFormat format) { 511 mProgressPercentFormat = format; 512 onProgressChanged(); 513 } 514 onProgressChanged()515 private void onProgressChanged() { 516 if (mProgressStyle == STYLE_HORIZONTAL) { 517 if (mViewUpdateHandler != null && !mViewUpdateHandler.hasMessages(0)) { 518 mViewUpdateHandler.sendEmptyMessage(0); 519 } 520 } 521 } 522 } 523