ProgressDialog.java revision 5d4faa91f7e3135d62f9cef730cbe876074937ee
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
17package android.app;
18
19import android.content.Context;
20import android.graphics.drawable.Drawable;
21import android.os.Bundle;
22import android.os.Handler;
23import android.os.Message;
24import android.text.Spannable;
25import android.text.SpannableString;
26import android.text.style.StyleSpan;
27import android.view.LayoutInflater;
28import android.view.View;
29import android.widget.ProgressBar;
30import android.widget.TextView;
31
32import com.android.internal.R;
33
34import java.text.NumberFormat;
35
36/**
37 * <p>A dialog showing a progress indicator and an optional text message or view.
38 * Only a text message or a view can be used at the same time.</p>
39 * <p>The dialog can be made cancelable on back key press.</p>
40 * <p>The progress range is 0..10000.</p>
41 */
42public class ProgressDialog extends AlertDialog {
43
44    /** Creates a ProgressDialog with a circular, spinning progress
45     * bar. This is the default.
46     */
47    public static final int STYLE_SPINNER = 0;
48
49    /** Creates a ProgressDialog with a horizontal progress bar.
50     */
51    public static final int STYLE_HORIZONTAL = 1;
52
53    private ProgressBar mProgress;
54    private TextView mMessageView;
55
56    private int mProgressStyle = STYLE_SPINNER;
57    private TextView mProgressNumber;
58    private String mProgressNumberFormat;
59    private TextView mProgressPercent;
60    private NumberFormat mProgressPercentFormat;
61
62    private int mMax;
63    private int mProgressVal;
64    private int mSecondaryProgressVal;
65    private int mIncrementBy;
66    private int mIncrementSecondaryBy;
67    private Drawable mProgressDrawable;
68    private Drawable mIndeterminateDrawable;
69    private CharSequence mMessage;
70    private boolean mIndeterminate;
71
72    private boolean mHasStarted;
73    private Handler mViewUpdateHandler;
74
75    public ProgressDialog(Context context) {
76        super(context);
77        initFormats();
78    }
79
80    public ProgressDialog(Context context, int theme) {
81        super(context, theme);
82        initFormats();
83    }
84
85    private void initFormats() {
86        mProgressNumberFormat = "%1d/%2d";
87        mProgressPercentFormat = NumberFormat.getPercentInstance();
88        mProgressPercentFormat.setMaximumFractionDigits(0);
89    }
90
91    public static ProgressDialog show(Context context, CharSequence title,
92            CharSequence message) {
93        return show(context, title, message, false);
94    }
95
96    public static ProgressDialog show(Context context, CharSequence title,
97            CharSequence message, boolean indeterminate) {
98        return show(context, title, message, indeterminate, false, null);
99    }
100
101    public static ProgressDialog show(Context context, CharSequence title,
102            CharSequence message, boolean indeterminate, boolean cancelable) {
103        return show(context, title, message, indeterminate, cancelable, null);
104    }
105
106    public static ProgressDialog show(Context context, CharSequence title,
107            CharSequence message, boolean indeterminate,
108            boolean cancelable, OnCancelListener cancelListener) {
109        ProgressDialog dialog = new ProgressDialog(context);
110        dialog.setTitle(title);
111        dialog.setMessage(message);
112        dialog.setIndeterminate(indeterminate);
113        dialog.setCancelable(cancelable);
114        dialog.setOnCancelListener(cancelListener);
115        dialog.show();
116        return dialog;
117    }
118
119    @Override
120    protected void onCreate(Bundle savedInstanceState) {
121        LayoutInflater inflater = LayoutInflater.from(mContext);
122        if (mProgressStyle == STYLE_HORIZONTAL) {
123
124            /* Use a separate handler to update the text views as they
125             * must be updated on the same thread that created them.
126             */
127            mViewUpdateHandler = new Handler() {
128                @Override
129                public void handleMessage(Message msg) {
130                    super.handleMessage(msg);
131
132                    /* Update the number and percent */
133                    int progress = mProgress.getProgress();
134                    int max = mProgress.getMax();
135                    if (mProgressNumberFormat != null) {
136                        String format = mProgressNumberFormat;
137                        mProgressNumber.setText(String.format(format, progress, max));
138                    } else {
139                        mProgressNumber.setText("");
140                    }
141                    if (mProgressPercentFormat != null) {
142                        double percent = (double) progress / (double) max;
143                        SpannableString tmp = new SpannableString(mProgressPercentFormat.format(percent));
144                        tmp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
145                                0, tmp.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
146                        mProgressPercent.setText(tmp);
147                    } else {
148                        mProgressPercent.setText("");
149                    }
150                }
151            };
152            View view = inflater.inflate(R.layout.alert_dialog_progress, null);
153            mProgress = (ProgressBar) view.findViewById(R.id.progress);
154            mProgressNumber = (TextView) view.findViewById(R.id.progress_number);
155            mProgressPercent = (TextView) view.findViewById(R.id.progress_percent);
156            setView(view);
157        } else {
158            View view = inflater.inflate(R.layout.progress_dialog, null);
159            mProgress = (ProgressBar) view.findViewById(R.id.progress);
160            mMessageView = (TextView) view.findViewById(R.id.message);
161            setView(view);
162        }
163        if (mMax > 0) {
164            setMax(mMax);
165        }
166        if (mProgressVal > 0) {
167            setProgress(mProgressVal);
168        }
169        if (mSecondaryProgressVal > 0) {
170            setSecondaryProgress(mSecondaryProgressVal);
171        }
172        if (mIncrementBy > 0) {
173            incrementProgressBy(mIncrementBy);
174        }
175        if (mIncrementSecondaryBy > 0) {
176            incrementSecondaryProgressBy(mIncrementSecondaryBy);
177        }
178        if (mProgressDrawable != null) {
179            setProgressDrawable(mProgressDrawable);
180        }
181        if (mIndeterminateDrawable != null) {
182            setIndeterminateDrawable(mIndeterminateDrawable);
183        }
184        if (mMessage != null) {
185            setMessage(mMessage);
186        }
187        setIndeterminate(mIndeterminate);
188        onProgressChanged();
189        super.onCreate(savedInstanceState);
190    }
191
192    @Override
193    public void onStart() {
194        super.onStart();
195        mHasStarted = true;
196    }
197
198    @Override
199    protected void onStop() {
200        super.onStop();
201        mHasStarted = false;
202    }
203
204    public void setProgress(int value) {
205        if (mHasStarted) {
206            mProgress.setProgress(value);
207            onProgressChanged();
208        } else {
209            mProgressVal = value;
210        }
211    }
212
213    public void setSecondaryProgress(int secondaryProgress) {
214        if (mProgress != null) {
215            mProgress.setSecondaryProgress(secondaryProgress);
216            onProgressChanged();
217        } else {
218            mSecondaryProgressVal = secondaryProgress;
219        }
220    }
221
222    public int getProgress() {
223        if (mProgress != null) {
224            return mProgress.getProgress();
225        }
226        return mProgressVal;
227    }
228
229    public int getSecondaryProgress() {
230        if (mProgress != null) {
231            return mProgress.getSecondaryProgress();
232        }
233        return mSecondaryProgressVal;
234    }
235
236    public int getMax() {
237        if (mProgress != null) {
238            return mProgress.getMax();
239        }
240        return mMax;
241    }
242
243    public void setMax(int max) {
244        if (mProgress != null) {
245            mProgress.setMax(max);
246            onProgressChanged();
247        } else {
248            mMax = max;
249        }
250    }
251
252    public void incrementProgressBy(int diff) {
253        if (mProgress != null) {
254            mProgress.incrementProgressBy(diff);
255            onProgressChanged();
256        } else {
257            mIncrementBy += diff;
258        }
259    }
260
261    public void incrementSecondaryProgressBy(int diff) {
262        if (mProgress != null) {
263            mProgress.incrementSecondaryProgressBy(diff);
264            onProgressChanged();
265        } else {
266            mIncrementSecondaryBy += diff;
267        }
268    }
269
270    public void setProgressDrawable(Drawable d) {
271        if (mProgress != null) {
272            mProgress.setProgressDrawable(d);
273        } else {
274            mProgressDrawable = d;
275        }
276    }
277
278    public void setIndeterminateDrawable(Drawable d) {
279        if (mProgress != null) {
280            mProgress.setIndeterminateDrawable(d);
281        } else {
282            mIndeterminateDrawable = d;
283        }
284    }
285
286    public void setIndeterminate(boolean indeterminate) {
287        if (mProgress != null) {
288            mProgress.setIndeterminate(indeterminate);
289        } else {
290            mIndeterminate = indeterminate;
291        }
292    }
293
294    public boolean isIndeterminate() {
295        if (mProgress != null) {
296            return mProgress.isIndeterminate();
297        }
298        return mIndeterminate;
299    }
300
301    @Override
302    public void setMessage(CharSequence message) {
303        if (mProgress != null) {
304            if (mProgressStyle == STYLE_HORIZONTAL) {
305                super.setMessage(message);
306            } else {
307                mMessageView.setText(message);
308            }
309        } else {
310            mMessage = message;
311        }
312    }
313
314    public void setProgressStyle(int style) {
315        mProgressStyle = style;
316    }
317
318    /**
319     * Change the format of the small text showing current and maximum units
320     * of progress.  The default is "%1d/%2d".
321     * Should not be called during the number is progressing.
322     * @param format A string passed to {@link String#format String.format()};
323     * use "%1d" for the current number and "%2d" for the maximum.  If null,
324     * nothing will be shown.
325     */
326    public void setProgressNumberFormat(String format) {
327        mProgressNumberFormat = format;
328        onProgressChanged();
329    }
330
331    /**
332     * Change the format of the small text showing the percentage of progress.
333     * The default is
334     * {@link NumberFormat#getPercentInstance() NumberFormat.getPercentageInstnace().}
335     * Should not be called during the number is progressing.
336     * @param format An instance of a {@link NumberFormat} to generate the
337     * percentage text.  If null, nothing will be shown.
338     */
339    public void setProgressPercentFormat(NumberFormat format) {
340        mProgressPercentFormat = format;
341        onProgressChanged();
342    }
343
344    private void onProgressChanged() {
345        if (mProgressStyle == STYLE_HORIZONTAL) {
346            if (mViewUpdateHandler != null && !mViewUpdateHandler.hasMessages(0)) {
347                mViewUpdateHandler.sendEmptyMessage(0);
348            }
349        }
350    }
351}
352