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