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