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