1 /* 2 * Copyright (C) 2015 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.support.v7.app; 18 19 import android.app.Dialog; 20 import android.content.Context; 21 import android.content.DialogInterface; 22 import android.database.Cursor; 23 import android.graphics.drawable.Drawable; 24 import android.os.Bundle; 25 import android.os.Message; 26 import android.support.annotation.ArrayRes; 27 import android.support.annotation.AttrRes; 28 import android.support.annotation.DrawableRes; 29 import android.support.annotation.NonNull; 30 import android.support.annotation.Nullable; 31 import android.support.annotation.StringRes; 32 import android.support.annotation.StyleRes; 33 import android.support.v7.appcompat.R; 34 import android.util.TypedValue; 35 import android.view.ContextThemeWrapper; 36 import android.view.KeyEvent; 37 import android.view.View; 38 import android.view.WindowManager; 39 import android.widget.AdapterView; 40 import android.widget.Button; 41 import android.widget.ListAdapter; 42 import android.widget.ListView; 43 44 /** 45 * A subclass of Dialog that can display one, two or three buttons. If you only want to 46 * display a String in this dialog box, use the setMessage() method. If you 47 * want to display a more complex view, look up the FrameLayout called "custom" 48 * and add your view to it: 49 * 50 * <pre> 51 * FrameLayout fl = (FrameLayout) findViewById(android.R.id.custom); 52 * fl.addView(myView, new LayoutParams(MATCH_PARENT, WRAP_CONTENT)); 53 * </pre> 54 * 55 * <p>The AlertDialog class takes care of automatically setting 56 * {@link WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM 57 * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} for you based on whether 58 * any views in the dialog return true from {@link View#onCheckIsTextEditor() 59 * View.onCheckIsTextEditor()}. Generally you want this set for a Dialog 60 * without text editors, so that it will be placed on top of the current 61 * input method UI. You can modify this behavior by forcing the flag to your 62 * desired mode after calling {@link #onCreate}. 63 * 64 * <div class="special reference"> 65 * <h3>Developer Guides</h3> 66 * <p>For more information about creating dialogs, read the 67 * <a href="{@docRoot}guide/topics/ui/dialogs.html">Dialogs</a> developer guide.</p> 68 * </div> 69 */ 70 public class AlertDialog extends AppCompatDialog implements DialogInterface { 71 72 private final AlertController mAlert; 73 74 /** 75 * No layout hint. 76 */ 77 static final int LAYOUT_HINT_NONE = 0; 78 79 /** 80 * Hint layout to the side. 81 */ 82 static final int LAYOUT_HINT_SIDE = 1; 83 AlertDialog(@onNull Context context)84 protected AlertDialog(@NonNull Context context) { 85 this(context, 0); 86 } 87 88 /** 89 * Construct an AlertDialog that uses an explicit theme. The actual style 90 * that an AlertDialog uses is a private implementation, however you can 91 * here supply either the name of an attribute in the theme from which 92 * to get the dialog's style (such as {@link R.attr#alertDialogTheme}. 93 */ AlertDialog(@onNull Context context, @StyleRes int themeResId)94 protected AlertDialog(@NonNull Context context, @StyleRes int themeResId) { 95 super(context, resolveDialogTheme(context, themeResId)); 96 mAlert = new AlertController(getContext(), this, getWindow()); 97 } 98 AlertDialog(@onNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener)99 protected AlertDialog(@NonNull Context context, boolean cancelable, 100 @Nullable OnCancelListener cancelListener) { 101 this(context, 0); 102 setCancelable(cancelable); 103 setOnCancelListener(cancelListener); 104 } 105 resolveDialogTheme(@onNull Context context, @StyleRes int resid)106 private static int resolveDialogTheme(@NonNull Context context, @StyleRes int resid) { 107 if (resid >= 0x01000000) { // start of real resource IDs. 108 return resid; 109 } else { 110 TypedValue outValue = new TypedValue(); 111 context.getTheme().resolveAttribute(R.attr.alertDialogTheme, outValue, true); 112 return outValue.resourceId; 113 } 114 } 115 116 /** 117 * Gets one of the buttons used in the dialog. Returns null if the specified 118 * button does not exist or the dialog has not yet been fully created (for 119 * example, via {@link #show()} or {@link #create()}). 120 * 121 * @param whichButton The identifier of the button that should be returned. 122 * For example, this can be 123 * {@link DialogInterface#BUTTON_POSITIVE}. 124 * @return The button from the dialog, or null if a button does not exist. 125 */ getButton(int whichButton)126 public Button getButton(int whichButton) { 127 return mAlert.getButton(whichButton); 128 } 129 130 /** 131 * Gets the list view used in the dialog. 132 * 133 * @return The {@link ListView} from the dialog. 134 */ getListView()135 public ListView getListView() { 136 return mAlert.getListView(); 137 } 138 139 @Override setTitle(CharSequence title)140 public void setTitle(CharSequence title) { 141 super.setTitle(title); 142 mAlert.setTitle(title); 143 } 144 145 /** 146 * @see Builder#setCustomTitle(View) 147 * 148 * This method has no effect if called after {@link #show()}. 149 */ setCustomTitle(View customTitleView)150 public void setCustomTitle(View customTitleView) { 151 mAlert.setCustomTitle(customTitleView); 152 } 153 154 /** 155 * Sets the message to display. 156 * 157 * @param message The message to display in the dialog. 158 */ setMessage(CharSequence message)159 public void setMessage(CharSequence message) { 160 mAlert.setMessage(message); 161 } 162 163 /** 164 * Set the view to display in the dialog. This method has no effect if called 165 * after {@link #show()}. 166 */ setView(View view)167 public void setView(View view) { 168 mAlert.setView(view); 169 } 170 171 /** 172 * Set the view to display in the dialog, specifying the spacing to appear around that 173 * view. This method has no effect if called after {@link #show()}. 174 * 175 * @param view The view to show in the content area of the dialog 176 * @param viewSpacingLeft Extra space to appear to the left of {@code view} 177 * @param viewSpacingTop Extra space to appear above {@code view} 178 * @param viewSpacingRight Extra space to appear to the right of {@code view} 179 * @param viewSpacingBottom Extra space to appear below {@code view} 180 */ setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom)181 public void setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, 182 int viewSpacingBottom) { 183 mAlert.setView(view, viewSpacingLeft, viewSpacingTop, viewSpacingRight, viewSpacingBottom); 184 } 185 186 /** 187 * Internal api to allow hinting for the best button panel layout. 188 * 189 * @hide 190 */ setButtonPanelLayoutHint(int layoutHint)191 void setButtonPanelLayoutHint(int layoutHint) { 192 mAlert.setButtonPanelLayoutHint(layoutHint); 193 } 194 195 /** 196 * Sets a message to be sent when a button is pressed. This method has no effect if called 197 * after {@link #show()}. 198 * 199 * @param whichButton Which button to set the message for, can be one of 200 * {@link DialogInterface#BUTTON_POSITIVE}, 201 * {@link DialogInterface#BUTTON_NEGATIVE}, or 202 * {@link DialogInterface#BUTTON_NEUTRAL} 203 * @param text The text to display in positive button. 204 * @param msg The {@link Message} to be sent when clicked. 205 */ setButton(int whichButton, CharSequence text, Message msg)206 public void setButton(int whichButton, CharSequence text, Message msg) { 207 mAlert.setButton(whichButton, text, null, msg); 208 } 209 210 /** 211 * Sets a listener to be invoked when the positive button of the dialog is pressed. This method 212 * has no effect if called after {@link #show()}. 213 * 214 * @param whichButton Which button to set the listener on, can be one of 215 * {@link DialogInterface#BUTTON_POSITIVE}, 216 * {@link DialogInterface#BUTTON_NEGATIVE}, or 217 * {@link DialogInterface#BUTTON_NEUTRAL} 218 * @param text The text to display in positive button. 219 * @param listener The {@link DialogInterface.OnClickListener} to use. 220 */ setButton(int whichButton, CharSequence text, OnClickListener listener)221 public void setButton(int whichButton, CharSequence text, OnClickListener listener) { 222 mAlert.setButton(whichButton, text, listener, null); 223 } 224 225 /** 226 * Set resId to 0 if you don't want an icon. 227 * @param resId the resourceId of the drawable to use as the icon or 0 228 * if you don't want an icon. 229 */ setIcon(int resId)230 public void setIcon(int resId) { 231 mAlert.setIcon(resId); 232 } 233 234 /** 235 * Set the {@link Drawable} to be used in the title. 236 * 237 * @param icon Drawable to use as the icon or null if you don't want an icon. 238 */ setIcon(Drawable icon)239 public void setIcon(Drawable icon) { 240 mAlert.setIcon(icon); 241 } 242 243 /** 244 * Sets an icon as supplied by a theme attribute. e.g. android.R.attr.alertDialogIcon 245 * 246 * @param attrId ID of a theme attribute that points to a drawable resource. 247 */ setIconAttribute(int attrId)248 public void setIconAttribute(int attrId) { 249 TypedValue out = new TypedValue(); 250 getContext().getTheme().resolveAttribute(attrId, out, true); 251 mAlert.setIcon(out.resourceId); 252 } 253 254 @Override onCreate(Bundle savedInstanceState)255 protected void onCreate(Bundle savedInstanceState) { 256 super.onCreate(savedInstanceState); 257 mAlert.installContent(); 258 } 259 260 @Override onKeyDown(int keyCode, KeyEvent event)261 public boolean onKeyDown(int keyCode, KeyEvent event) { 262 if (mAlert.onKeyDown(keyCode, event)) { 263 return true; 264 } 265 return super.onKeyDown(keyCode, event); 266 } 267 268 @Override onKeyUp(int keyCode, KeyEvent event)269 public boolean onKeyUp(int keyCode, KeyEvent event) { 270 if (mAlert.onKeyUp(keyCode, event)) { 271 return true; 272 } 273 return super.onKeyUp(keyCode, event); 274 } 275 276 public static class Builder { 277 private final AlertController.AlertParams P; 278 private final int mTheme; 279 280 /** 281 * Creates a builder for an alert dialog that uses the default alert 282 * dialog theme. 283 * <p> 284 * The default alert dialog theme is defined by 285 * {@link android.R.attr#alertDialogTheme} within the parent 286 * {@code context}'s theme. 287 * 288 * @param context the parent context 289 */ Builder(@onNull Context context)290 public Builder(@NonNull Context context) { 291 this(context, resolveDialogTheme(context, 0)); 292 } 293 294 /** 295 * Creates a builder for an alert dialog that uses an explicit theme 296 * resource. 297 * <p> 298 * The specified theme resource ({@code themeResId}) is applied on top 299 * of the parent {@code context}'s theme. It may be specified as a 300 * style resource containing a fully-populated theme, such as 301 * {@link R.style#Theme_AppCompat_Dialog}, to replace all 302 * attributes in the parent {@code context}'s theme including primary 303 * and accent colors. 304 * <p> 305 * To preserve attributes such as primary and accent colors, the 306 * {@code themeResId} may instead be specified as an overlay theme such 307 * as {@link R.style#ThemeOverlay_AppCompat_Dialog}. This will 308 * override only the window attributes necessary to style the alert 309 * window as a dialog. 310 * <p> 311 * Alternatively, the {@code themeResId} may be specified as {@code 0} 312 * to use the parent {@code context}'s resolved value for 313 * {@link android.R.attr#alertDialogTheme}. 314 * 315 * @param context the parent context 316 * @param themeResId the resource ID of the theme against which to inflate 317 * this dialog, or {@code 0} to use the parent 318 * {@code context}'s default alert dialog theme 319 */ Builder(@onNull Context context, @StyleRes int themeResId)320 public Builder(@NonNull Context context, @StyleRes int themeResId) { 321 P = new AlertController.AlertParams(new ContextThemeWrapper( 322 context, resolveDialogTheme(context, themeResId))); 323 mTheme = themeResId; 324 } 325 326 /** 327 * Returns a {@link Context} with the appropriate theme for dialogs created by this Builder. 328 * Applications should use this Context for obtaining LayoutInflaters for inflating views 329 * that will be used in the resulting dialogs, as it will cause views to be inflated with 330 * the correct theme. 331 * 332 * @return A Context for built Dialogs. 333 */ 334 @NonNull getContext()335 public Context getContext() { 336 return P.mContext; 337 } 338 339 /** 340 * Set the title using the given resource id. 341 * 342 * @return This Builder object to allow for chaining of calls to set methods 343 */ setTitle(@tringRes int titleId)344 public Builder setTitle(@StringRes int titleId) { 345 P.mTitle = P.mContext.getText(titleId); 346 return this; 347 } 348 349 /** 350 * Set the title displayed in the {@link Dialog}. 351 * 352 * @return This Builder object to allow for chaining of calls to set methods 353 */ setTitle(CharSequence title)354 public Builder setTitle(CharSequence title) { 355 P.mTitle = title; 356 return this; 357 } 358 359 /** 360 * Set the title using the custom view {@code customTitleView}. 361 * <p> 362 * The methods {@link #setTitle(int)} and {@link #setIcon(int)} should 363 * be sufficient for most titles, but this is provided if the title 364 * needs more customization. Using this will replace the title and icon 365 * set via the other methods. 366 * <p> 367 * <strong>Note:</strong> To ensure consistent styling, the custom view 368 * should be inflated or constructed using the alert dialog's themed 369 * context obtained via {@link #getContext()}. 370 * 371 * @param customTitleView the custom view to use as the title 372 * @return this Builder object to allow for chaining of calls to set 373 * methods 374 */ setCustomTitle(View customTitleView)375 public Builder setCustomTitle(View customTitleView) { 376 P.mCustomTitleView = customTitleView; 377 return this; 378 } 379 380 /** 381 * Set the message to display using the given resource id. 382 * 383 * @return This Builder object to allow for chaining of calls to set methods 384 */ setMessage(@tringRes int messageId)385 public Builder setMessage(@StringRes int messageId) { 386 P.mMessage = P.mContext.getText(messageId); 387 return this; 388 } 389 390 /** 391 * Set the message to display. 392 * 393 * @return This Builder object to allow for chaining of calls to set methods 394 */ setMessage(CharSequence message)395 public Builder setMessage(CharSequence message) { 396 P.mMessage = message; 397 return this; 398 } 399 400 /** 401 * Set the resource id of the {@link Drawable} to be used in the title. 402 * <p> 403 * Takes precedence over values set using {@link #setIcon(Drawable)}. 404 * 405 * @return This Builder object to allow for chaining of calls to set methods 406 */ setIcon(@rawableRes int iconId)407 public Builder setIcon(@DrawableRes int iconId) { 408 P.mIconId = iconId; 409 return this; 410 } 411 412 /** 413 * Set the {@link Drawable} to be used in the title. 414 * <p> 415 * <strong>Note:</strong> To ensure consistent styling, the drawable 416 * should be inflated or constructed using the alert dialog's themed 417 * context obtained via {@link #getContext()}. 418 * 419 * @return this Builder object to allow for chaining of calls to set 420 * methods 421 */ setIcon(Drawable icon)422 public Builder setIcon(Drawable icon) { 423 P.mIcon = icon; 424 return this; 425 } 426 427 /** 428 * Set an icon as supplied by a theme attribute. e.g. 429 * {@link android.R.attr#alertDialogIcon}. 430 * <p> 431 * Takes precedence over values set using {@link #setIcon(int)} or 432 * {@link #setIcon(Drawable)}. 433 * 434 * @param attrId ID of a theme attribute that points to a drawable resource. 435 */ setIconAttribute(@ttrRes int attrId)436 public Builder setIconAttribute(@AttrRes int attrId) { 437 TypedValue out = new TypedValue(); 438 P.mContext.getTheme().resolveAttribute(attrId, out, true); 439 P.mIconId = out.resourceId; 440 return this; 441 } 442 443 /** 444 * Set a listener to be invoked when the positive button of the dialog is pressed. 445 * @param textId The resource id of the text to display in the positive button 446 * @param listener The {@link DialogInterface.OnClickListener} to use. 447 * 448 * @return This Builder object to allow for chaining of calls to set methods 449 */ setPositiveButton(@tringRes int textId, final OnClickListener listener)450 public Builder setPositiveButton(@StringRes int textId, final OnClickListener listener) { 451 P.mPositiveButtonText = P.mContext.getText(textId); 452 P.mPositiveButtonListener = listener; 453 return this; 454 } 455 456 /** 457 * Set a listener to be invoked when the positive button of the dialog is pressed. 458 * @param text The text to display in the positive button 459 * @param listener The {@link DialogInterface.OnClickListener} to use. 460 * 461 * @return This Builder object to allow for chaining of calls to set methods 462 */ setPositiveButton(CharSequence text, final OnClickListener listener)463 public Builder setPositiveButton(CharSequence text, final OnClickListener listener) { 464 P.mPositiveButtonText = text; 465 P.mPositiveButtonListener = listener; 466 return this; 467 } 468 469 /** 470 * Set a listener to be invoked when the negative button of the dialog is pressed. 471 * @param textId The resource id of the text to display in the negative button 472 * @param listener The {@link DialogInterface.OnClickListener} to use. 473 * 474 * @return This Builder object to allow for chaining of calls to set methods 475 */ setNegativeButton(@tringRes int textId, final OnClickListener listener)476 public Builder setNegativeButton(@StringRes int textId, final OnClickListener listener) { 477 P.mNegativeButtonText = P.mContext.getText(textId); 478 P.mNegativeButtonListener = listener; 479 return this; 480 } 481 482 /** 483 * Set a listener to be invoked when the negative button of the dialog is pressed. 484 * @param text The text to display in the negative button 485 * @param listener The {@link DialogInterface.OnClickListener} to use. 486 * 487 * @return This Builder object to allow for chaining of calls to set methods 488 */ setNegativeButton(CharSequence text, final OnClickListener listener)489 public Builder setNegativeButton(CharSequence text, final OnClickListener listener) { 490 P.mNegativeButtonText = text; 491 P.mNegativeButtonListener = listener; 492 return this; 493 } 494 495 /** 496 * Set a listener to be invoked when the neutral button of the dialog is pressed. 497 * @param textId The resource id of the text to display in the neutral button 498 * @param listener The {@link DialogInterface.OnClickListener} to use. 499 * 500 * @return This Builder object to allow for chaining of calls to set methods 501 */ setNeutralButton(@tringRes int textId, final OnClickListener listener)502 public Builder setNeutralButton(@StringRes int textId, final OnClickListener listener) { 503 P.mNeutralButtonText = P.mContext.getText(textId); 504 P.mNeutralButtonListener = listener; 505 return this; 506 } 507 508 /** 509 * Set a listener to be invoked when the neutral button of the dialog is pressed. 510 * @param text The text to display in the neutral button 511 * @param listener The {@link DialogInterface.OnClickListener} to use. 512 * 513 * @return This Builder object to allow for chaining of calls to set methods 514 */ setNeutralButton(CharSequence text, final OnClickListener listener)515 public Builder setNeutralButton(CharSequence text, final OnClickListener listener) { 516 P.mNeutralButtonText = text; 517 P.mNeutralButtonListener = listener; 518 return this; 519 } 520 521 /** 522 * Sets whether the dialog is cancelable or not. Default is true. 523 * 524 * @return This Builder object to allow for chaining of calls to set methods 525 */ setCancelable(boolean cancelable)526 public Builder setCancelable(boolean cancelable) { 527 P.mCancelable = cancelable; 528 return this; 529 } 530 531 /** 532 * Sets the callback that will be called if the dialog is canceled. 533 * 534 * <p>Even in a cancelable dialog, the dialog may be dismissed for reasons other than 535 * being canceled or one of the supplied choices being selected. 536 * If you are interested in listening for all cases where the dialog is dismissed 537 * and not just when it is canceled, see 538 * {@link #setOnDismissListener(android.content.DialogInterface.OnDismissListener) 539 * setOnDismissListener}.</p> 540 * 541 * @return This Builder object to allow for chaining of calls to set methods 542 * @see #setCancelable(boolean) 543 * @see #setOnDismissListener(android.content.DialogInterface.OnDismissListener) 544 * 545 * @return This Builder object to allow for chaining of calls to set methods 546 */ setOnCancelListener(OnCancelListener onCancelListener)547 public Builder setOnCancelListener(OnCancelListener onCancelListener) { 548 P.mOnCancelListener = onCancelListener; 549 return this; 550 } 551 552 /** 553 * Sets the callback that will be called when the dialog is dismissed for any reason. 554 * 555 * @return This Builder object to allow for chaining of calls to set methods 556 */ setOnDismissListener(OnDismissListener onDismissListener)557 public Builder setOnDismissListener(OnDismissListener onDismissListener) { 558 P.mOnDismissListener = onDismissListener; 559 return this; 560 } 561 562 /** 563 * Sets the callback that will be called if a key is dispatched to the dialog. 564 * 565 * @return This Builder object to allow for chaining of calls to set methods 566 */ setOnKeyListener(OnKeyListener onKeyListener)567 public Builder setOnKeyListener(OnKeyListener onKeyListener) { 568 P.mOnKeyListener = onKeyListener; 569 return this; 570 } 571 572 /** 573 * Set a list of items to be displayed in the dialog as the content, you will be notified of the 574 * selected item via the supplied listener. This should be an array type i.e. R.array.foo 575 * 576 * @return This Builder object to allow for chaining of calls to set methods 577 */ setItems(@rrayRes int itemsId, final OnClickListener listener)578 public Builder setItems(@ArrayRes int itemsId, final OnClickListener listener) { 579 P.mItems = P.mContext.getResources().getTextArray(itemsId); 580 P.mOnClickListener = listener; 581 return this; 582 } 583 584 /** 585 * Set a list of items to be displayed in the dialog as the content, you will be notified of the 586 * selected item via the supplied listener. 587 * 588 * @return This Builder object to allow for chaining of calls to set methods 589 */ setItems(CharSequence[] items, final OnClickListener listener)590 public Builder setItems(CharSequence[] items, final OnClickListener listener) { 591 P.mItems = items; 592 P.mOnClickListener = listener; 593 return this; 594 } 595 596 /** 597 * Set a list of items, which are supplied by the given {@link ListAdapter}, to be 598 * displayed in the dialog as the content, you will be notified of the 599 * selected item via the supplied listener. 600 * 601 * @param adapter The {@link ListAdapter} to supply the list of items 602 * @param listener The listener that will be called when an item is clicked. 603 * 604 * @return This Builder object to allow for chaining of calls to set methods 605 */ setAdapter(final ListAdapter adapter, final OnClickListener listener)606 public Builder setAdapter(final ListAdapter adapter, final OnClickListener listener) { 607 P.mAdapter = adapter; 608 P.mOnClickListener = listener; 609 return this; 610 } 611 612 /** 613 * Set a list of items, which are supplied by the given {@link Cursor}, to be 614 * displayed in the dialog as the content, you will be notified of the 615 * selected item via the supplied listener. 616 * 617 * @param cursor The {@link Cursor} to supply the list of items 618 * @param listener The listener that will be called when an item is clicked. 619 * @param labelColumn The column name on the cursor containing the string to display 620 * in the label. 621 * 622 * @return This Builder object to allow for chaining of calls to set methods 623 */ setCursor(final Cursor cursor, final OnClickListener listener, String labelColumn)624 public Builder setCursor(final Cursor cursor, final OnClickListener listener, 625 String labelColumn) { 626 P.mCursor = cursor; 627 P.mLabelColumn = labelColumn; 628 P.mOnClickListener = listener; 629 return this; 630 } 631 632 /** 633 * Set a list of items to be displayed in the dialog as the content, 634 * you will be notified of the selected item via the supplied listener. 635 * This should be an array type, e.g. R.array.foo. The list will have 636 * a check mark displayed to the right of the text for each checked 637 * item. Clicking on an item in the list will not dismiss the dialog. 638 * Clicking on a button will dismiss the dialog. 639 * 640 * @param itemsId the resource id of an array i.e. R.array.foo 641 * @param checkedItems specifies which items are checked. It should be null in which case no 642 * items are checked. If non null it must be exactly the same length as the array of 643 * items. 644 * @param listener notified when an item on the list is clicked. The dialog will not be 645 * dismissed when an item is clicked. It will only be dismissed if clicked on a 646 * button, if no buttons are supplied it's up to the user to dismiss the dialog. 647 * 648 * @return This Builder object to allow for chaining of calls to set methods 649 */ setMultiChoiceItems(@rrayRes int itemsId, boolean[] checkedItems, final OnMultiChoiceClickListener listener)650 public Builder setMultiChoiceItems(@ArrayRes int itemsId, boolean[] checkedItems, 651 final OnMultiChoiceClickListener listener) { 652 P.mItems = P.mContext.getResources().getTextArray(itemsId); 653 P.mOnCheckboxClickListener = listener; 654 P.mCheckedItems = checkedItems; 655 P.mIsMultiChoice = true; 656 return this; 657 } 658 659 /** 660 * Set a list of items to be displayed in the dialog as the content, 661 * you will be notified of the selected item via the supplied listener. 662 * The list will have a check mark displayed to the right of the text 663 * for each checked item. Clicking on an item in the list will not 664 * dismiss the dialog. Clicking on a button will dismiss the dialog. 665 * 666 * @param items the text of the items to be displayed in the list. 667 * @param checkedItems specifies which items are checked. It should be null in which case no 668 * items are checked. If non null it must be exactly the same length as the array of 669 * items. 670 * @param listener notified when an item on the list is clicked. The dialog will not be 671 * dismissed when an item is clicked. It will only be dismissed if clicked on a 672 * button, if no buttons are supplied it's up to the user to dismiss the dialog. 673 * 674 * @return This Builder object to allow for chaining of calls to set methods 675 */ setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, final OnMultiChoiceClickListener listener)676 public Builder setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, 677 final OnMultiChoiceClickListener listener) { 678 P.mItems = items; 679 P.mOnCheckboxClickListener = listener; 680 P.mCheckedItems = checkedItems; 681 P.mIsMultiChoice = true; 682 return this; 683 } 684 685 /** 686 * Set a list of items to be displayed in the dialog as the content, 687 * you will be notified of the selected item via the supplied listener. 688 * The list will have a check mark displayed to the right of the text 689 * for each checked item. Clicking on an item in the list will not 690 * dismiss the dialog. Clicking on a button will dismiss the dialog. 691 * 692 * @param cursor the cursor used to provide the items. 693 * @param isCheckedColumn specifies the column name on the cursor to use to determine 694 * whether a checkbox is checked or not. It must return an integer value where 1 695 * means checked and 0 means unchecked. 696 * @param labelColumn The column name on the cursor containing the string to display in the 697 * label. 698 * @param listener notified when an item on the list is clicked. The dialog will not be 699 * dismissed when an item is clicked. It will only be dismissed if clicked on a 700 * button, if no buttons are supplied it's up to the user to dismiss the dialog. 701 * 702 * @return This Builder object to allow for chaining of calls to set methods 703 */ setMultiChoiceItems(Cursor cursor, String isCheckedColumn, String labelColumn, final OnMultiChoiceClickListener listener)704 public Builder setMultiChoiceItems(Cursor cursor, String isCheckedColumn, String labelColumn, 705 final OnMultiChoiceClickListener listener) { 706 P.mCursor = cursor; 707 P.mOnCheckboxClickListener = listener; 708 P.mIsCheckedColumn = isCheckedColumn; 709 P.mLabelColumn = labelColumn; 710 P.mIsMultiChoice = true; 711 return this; 712 } 713 714 /** 715 * Set a list of items to be displayed in the dialog as the content, you will be notified of 716 * the selected item via the supplied listener. This should be an array type i.e. 717 * R.array.foo The list will have a check mark displayed to the right of the text for the 718 * checked item. Clicking on an item in the list will not dismiss the dialog. Clicking on a 719 * button will dismiss the dialog. 720 * 721 * @param itemsId the resource id of an array i.e. R.array.foo 722 * @param checkedItem specifies which item is checked. If -1 no items are checked. 723 * @param listener notified when an item on the list is clicked. The dialog will not be 724 * dismissed when an item is clicked. It will only be dismissed if clicked on a 725 * button, if no buttons are supplied it's up to the user to dismiss the dialog. 726 * 727 * @return This Builder object to allow for chaining of calls to set methods 728 */ setSingleChoiceItems(@rrayRes int itemsId, int checkedItem, final OnClickListener listener)729 public Builder setSingleChoiceItems(@ArrayRes int itemsId, int checkedItem, 730 final OnClickListener listener) { 731 P.mItems = P.mContext.getResources().getTextArray(itemsId); 732 P.mOnClickListener = listener; 733 P.mCheckedItem = checkedItem; 734 P.mIsSingleChoice = true; 735 return this; 736 } 737 738 /** 739 * Set a list of items to be displayed in the dialog as the content, you will be notified of 740 * the selected item via the supplied listener. The list will have a check mark displayed to 741 * the right of the text for the checked item. Clicking on an item in the list will not 742 * dismiss the dialog. Clicking on a button will dismiss the dialog. 743 * 744 * @param cursor the cursor to retrieve the items from. 745 * @param checkedItem specifies which item is checked. If -1 no items are checked. 746 * @param labelColumn The column name on the cursor containing the string to display in the 747 * label. 748 * @param listener notified when an item on the list is clicked. The dialog will not be 749 * dismissed when an item is clicked. It will only be dismissed if clicked on a 750 * button, if no buttons are supplied it's up to the user to dismiss the dialog. 751 * 752 * @return This Builder object to allow for chaining of calls to set methods 753 */ setSingleChoiceItems(Cursor cursor, int checkedItem, String labelColumn, final OnClickListener listener)754 public Builder setSingleChoiceItems(Cursor cursor, int checkedItem, String labelColumn, 755 final OnClickListener listener) { 756 P.mCursor = cursor; 757 P.mOnClickListener = listener; 758 P.mCheckedItem = checkedItem; 759 P.mLabelColumn = labelColumn; 760 P.mIsSingleChoice = true; 761 return this; 762 } 763 764 /** 765 * Set a list of items to be displayed in the dialog as the content, you will be notified of 766 * the selected item via the supplied listener. The list will have a check mark displayed to 767 * the right of the text for the checked item. Clicking on an item in the list will not 768 * dismiss the dialog. Clicking on a button will dismiss the dialog. 769 * 770 * @param items the items to be displayed. 771 * @param checkedItem specifies which item is checked. If -1 no items are checked. 772 * @param listener notified when an item on the list is clicked. The dialog will not be 773 * dismissed when an item is clicked. It will only be dismissed if clicked on a 774 * button, if no buttons are supplied it's up to the user to dismiss the dialog. 775 * 776 * @return This Builder object to allow for chaining of calls to set methods 777 */ setSingleChoiceItems(CharSequence[] items, int checkedItem, final OnClickListener listener)778 public Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, final OnClickListener listener) { 779 P.mItems = items; 780 P.mOnClickListener = listener; 781 P.mCheckedItem = checkedItem; 782 P.mIsSingleChoice = true; 783 return this; 784 } 785 786 /** 787 * Set a list of items to be displayed in the dialog as the content, you will be notified of 788 * the selected item via the supplied listener. The list will have a check mark displayed to 789 * the right of the text for the checked item. Clicking on an item in the list will not 790 * dismiss the dialog. Clicking on a button will dismiss the dialog. 791 * 792 * @param adapter The {@link ListAdapter} to supply the list of items 793 * @param checkedItem specifies which item is checked. If -1 no items are checked. 794 * @param listener notified when an item on the list is clicked. The dialog will not be 795 * dismissed when an item is clicked. It will only be dismissed if clicked on a 796 * button, if no buttons are supplied it's up to the user to dismiss the dialog. 797 * 798 * @return This Builder object to allow for chaining of calls to set methods 799 */ setSingleChoiceItems(ListAdapter adapter, int checkedItem, final OnClickListener listener)800 public Builder setSingleChoiceItems(ListAdapter adapter, int checkedItem, final OnClickListener listener) { 801 P.mAdapter = adapter; 802 P.mOnClickListener = listener; 803 P.mCheckedItem = checkedItem; 804 P.mIsSingleChoice = true; 805 return this; 806 } 807 808 /** 809 * Sets a listener to be invoked when an item in the list is selected. 810 * 811 * @param listener the listener to be invoked 812 * @return this Builder object to allow for chaining of calls to set methods 813 * @see AdapterView#setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener) 814 */ setOnItemSelectedListener(final AdapterView.OnItemSelectedListener listener)815 public Builder setOnItemSelectedListener(final AdapterView.OnItemSelectedListener listener) { 816 P.mOnItemSelectedListener = listener; 817 return this; 818 } 819 820 /** 821 * Set a custom view resource to be the contents of the Dialog. The 822 * resource will be inflated, adding all top-level views to the screen. 823 * 824 * @param layoutResId Resource ID to be inflated. 825 * @return this Builder object to allow for chaining of calls to set 826 * methods 827 */ setView(int layoutResId)828 public Builder setView(int layoutResId) { 829 P.mView = null; 830 P.mViewLayoutResId = layoutResId; 831 P.mViewSpacingSpecified = false; 832 return this; 833 } 834 835 /** 836 * Sets a custom view to be the contents of the alert dialog. 837 * <p> 838 * When using a pre-Holo theme, if the supplied view is an instance of 839 * a {@link ListView} then the light background will be used. 840 * <p> 841 * <strong>Note:</strong> To ensure consistent styling, the custom view 842 * should be inflated or constructed using the alert dialog's themed 843 * context obtained via {@link #getContext()}. 844 * 845 * @param view the view to use as the contents of the alert dialog 846 * @return this Builder object to allow for chaining of calls to set 847 * methods 848 */ setView(View view)849 public Builder setView(View view) { 850 P.mView = view; 851 P.mViewLayoutResId = 0; 852 P.mViewSpacingSpecified = false; 853 return this; 854 } 855 856 /** 857 * Set a custom view to be the contents of the Dialog, specifying the 858 * spacing to appear around that view. If the supplied view is an 859 * instance of a {@link ListView} the light background will be used. 860 * 861 * @param view The view to use as the contents of the Dialog. 862 * @param viewSpacingLeft Spacing between the left edge of the view and 863 * the dialog frame 864 * @param viewSpacingTop Spacing between the top edge of the view and 865 * the dialog frame 866 * @param viewSpacingRight Spacing between the right edge of the view 867 * and the dialog frame 868 * @param viewSpacingBottom Spacing between the bottom edge of the view 869 * and the dialog frame 870 * @return This Builder object to allow for chaining of calls to set 871 * methods 872 * 873 * 874 * This is currently hidden because it seems like people should just 875 * be able to put padding around the view. 876 * @hide 877 */ 878 @Deprecated setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom)879 public Builder setView(View view, int viewSpacingLeft, int viewSpacingTop, 880 int viewSpacingRight, int viewSpacingBottom) { 881 P.mView = view; 882 P.mViewLayoutResId = 0; 883 P.mViewSpacingSpecified = true; 884 P.mViewSpacingLeft = viewSpacingLeft; 885 P.mViewSpacingTop = viewSpacingTop; 886 P.mViewSpacingRight = viewSpacingRight; 887 P.mViewSpacingBottom = viewSpacingBottom; 888 return this; 889 } 890 891 /** 892 * Sets the Dialog to use the inverse background, regardless of what the 893 * contents is. 894 * 895 * @param useInverseBackground Whether to use the inverse background 896 * @return This Builder object to allow for chaining of calls to set methods 897 * @deprecated This flag is only used for pre-Material themes. Instead, 898 * specify the window background using on the alert dialog 899 * theme. 900 */ 901 @Deprecated setInverseBackgroundForced(boolean useInverseBackground)902 public Builder setInverseBackgroundForced(boolean useInverseBackground) { 903 P.mForceInverseBackground = useInverseBackground; 904 return this; 905 } 906 907 /** 908 * @hide 909 */ setRecycleOnMeasureEnabled(boolean enabled)910 public Builder setRecycleOnMeasureEnabled(boolean enabled) { 911 P.mRecycleOnMeasure = enabled; 912 return this; 913 } 914 915 916 /** 917 * Creates an {@link AlertDialog} with the arguments supplied to this 918 * builder. 919 * <p> 920 * Calling this method does not display the dialog. If no additional 921 * processing is needed, {@link #show()} may be called instead to both 922 * create and display the dialog. 923 */ create()924 public AlertDialog create() { 925 // We can't use Dialog's 3-arg constructor with the createThemeContextWrapper param, 926 // so we always have to re-set the theme 927 final AlertDialog dialog = new AlertDialog(P.mContext, mTheme); 928 P.apply(dialog.mAlert); 929 dialog.setCancelable(P.mCancelable); 930 if (P.mCancelable) { 931 dialog.setCanceledOnTouchOutside(true); 932 } 933 dialog.setOnCancelListener(P.mOnCancelListener); 934 dialog.setOnDismissListener(P.mOnDismissListener); 935 if (P.mOnKeyListener != null) { 936 dialog.setOnKeyListener(P.mOnKeyListener); 937 } 938 return dialog; 939 } 940 941 /** 942 * Creates an {@link AlertDialog} with the arguments supplied to this 943 * builder and immediately displays the dialog. 944 * <p> 945 * Calling this method is functionally identical to: 946 * <pre> 947 * AlertDialog dialog = builder.create(); 948 * dialog.show(); 949 * </pre> 950 */ show()951 public AlertDialog show() { 952 final AlertDialog dialog = create(); 953 dialog.show(); 954 return dialog; 955 } 956 } 957 958 } 959