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