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