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