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