• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static android.support.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.support.annotation.ArrayRes;
29 import android.support.annotation.AttrRes;
30 import android.support.annotation.DrawableRes;
31 import android.support.annotation.NonNull;
32 import android.support.annotation.Nullable;
33 import android.support.annotation.RestrictTo;
34 import android.support.annotation.StringRes;
35 import android.support.annotation.StyleRes;
36 import android.support.v7.appcompat.R;
37 import android.util.TypedValue;
38 import android.view.ContextThemeWrapper;
39 import android.view.KeyEvent;
40 import android.view.View;
41 import android.widget.AdapterView;
42 import android.widget.Button;
43 import android.widget.ListAdapter;
44 import 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  */
72 public 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 
AlertDialog(@onNull Context context)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      */
AlertDialog(@onNull Context context, @StyleRes int themeResId)96     protected AlertDialog(@NonNull Context context, @StyleRes int themeResId) {
97         super(context, resolveDialogTheme(context, themeResId));
98         mAlert = new AlertController(getContext(), this, getWindow());
99     }
100 
AlertDialog(@onNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener)101     protected AlertDialog(@NonNull Context context, boolean cancelable,
102             @Nullable OnCancelListener cancelListener) {
103         this(context, 0);
104         setCancelable(cancelable);
105         setOnCancelListener(cancelListener);
106     }
107 
resolveDialogTheme(@onNull Context context, @StyleRes int resid)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      */
getButton(int whichButton)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      */
getListView()138     public ListView getListView() {
139         return mAlert.getListView();
140     }
141 
142     @Override
setTitle(CharSequence title)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      */
setCustomTitle(View customTitleView)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      */
setMessage(CharSequence message)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      */
setView(View view)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      */
setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom)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)
setButtonPanelLayoutHint(int layoutHint)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      */
setButton(int whichButton, CharSequence text, Message msg)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      */
setButton(int whichButton, CharSequence text, OnClickListener listener)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      */
setIcon(int resId)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      */
setIcon(Drawable icon)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      */
setIconAttribute(int attrId)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
onCreate(Bundle savedInstanceState)258     protected void onCreate(Bundle savedInstanceState) {
259         super.onCreate(savedInstanceState);
260         mAlert.installContent();
261     }
262 
263     @Override
onKeyDown(int keyCode, KeyEvent event)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
onKeyUp(int keyCode, KeyEvent event)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          */
Builder(@onNull Context context)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          */
Builder(@onNull Context context, @StyleRes int themeResId)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
getContext()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          */
setTitle(@tringRes int titleId)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          */
setTitle(@ullable CharSequence title)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          */
setCustomTitle(@ullable View customTitleView)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          */
setMessage(@tringRes int messageId)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          */
setMessage(@ullable CharSequence message)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          */
setIcon(@rawableRes int iconId)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          */
setIcon(@ullable Drawable icon)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          */
setIconAttribute(@ttrRes int attrId)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          */
setPositiveButton(@tringRes int textId, final OnClickListener listener)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          */
setPositiveButton(CharSequence text, final OnClickListener listener)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          */
setNegativeButton(@tringRes int textId, final OnClickListener listener)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          */
setNegativeButton(CharSequence text, final OnClickListener listener)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          */
setNeutralButton(@tringRes int textId, final OnClickListener listener)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          */
setNeutralButton(CharSequence text, final OnClickListener listener)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          */
setCancelable(boolean cancelable)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          */
setOnCancelListener(OnCancelListener onCancelListener)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          */
setOnDismissListener(OnDismissListener onDismissListener)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          */
setOnKeyListener(OnKeyListener onKeyListener)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          */
setItems(@rrayRes int itemsId, final OnClickListener listener)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          */
setItems(CharSequence[] items, final OnClickListener listener)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          */
setAdapter(final ListAdapter adapter, final OnClickListener listener)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          */
setCursor(final Cursor cursor, final OnClickListener listener, String labelColumn)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          */
setMultiChoiceItems(@rrayRes int itemsId, boolean[] checkedItems, final OnMultiChoiceClickListener listener)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          */
setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, final OnMultiChoiceClickListener listener)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          */
setMultiChoiceItems(Cursor cursor, String isCheckedColumn, String labelColumn, final OnMultiChoiceClickListener listener)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          */
setSingleChoiceItems(@rrayRes int itemsId, int checkedItem, final OnClickListener listener)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          */
setSingleChoiceItems(Cursor cursor, int checkedItem, String labelColumn, final OnClickListener listener)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          */
setSingleChoiceItems(CharSequence[] items, int checkedItem, final OnClickListener listener)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          */
setSingleChoiceItems(ListAdapter adapter, int checkedItem, final OnClickListener listener)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          */
setOnItemSelectedListener(final AdapterView.OnItemSelectedListener listener)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          */
setView(int layoutResId)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          */
setView(View view)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
setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom)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
setInverseBackgroundForced(boolean useInverseBackground)906         public Builder setInverseBackgroundForced(boolean useInverseBackground) {
907             P.mForceInverseBackground = useInverseBackground;
908             return this;
909         }
910 
911         /**
912          * @hide
913          */
914         @RestrictTo(LIBRARY_GROUP)
setRecycleOnMeasureEnabled(boolean enabled)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          */
create()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          */
show()956         public AlertDialog show() {
957             final AlertDialog dialog = create();
958             dialog.show();
959             return dialog;
960         }
961     }
962 
963 }
964