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          * <p>
    470          * Takes precedence over values set using {@link #setIcon(Drawable)}.
    471          *
    472          * @return This Builder object to allow for chaining of calls to set methods
    473          */
    474         public Builder setIcon(int iconId) {
    475             P.mIconId = iconId;
    476             return this;
    477         }
    478 
    479         /**
    480          * Set the {@link Drawable} to be used in the title.
    481           *
    482          * @return This Builder object to allow for chaining of calls to set methods
    483          */
    484         public Builder setIcon(Drawable icon) {
    485             P.mIcon = icon;
    486             return this;
    487         }
    488 
    489         /**
    490          * Set an icon as supplied by a theme attribute. e.g.
    491          * {@link android.R.attr#alertDialogIcon}.
    492          * <p>
    493          * Takes precedence over values set using {@link #setIcon(int)} or
    494          * {@link #setIcon(Drawable)}.
    495          *
    496          * @param attrId ID of a theme attribute that points to a drawable resource.
    497          */
    498         public Builder setIconAttribute(int attrId) {
    499             TypedValue out = new TypedValue();
    500             P.mContext.getTheme().resolveAttribute(attrId, out, true);
    501             P.mIconId = out.resourceId;
    502             return this;
    503         }
    504 
    505         /**
    506          * Set a listener to be invoked when the positive button of the dialog is pressed.
    507          * @param textId The resource id of the text to display in the positive button
    508          * @param listener The {@link DialogInterface.OnClickListener} to use.
    509          *
    510          * @return This Builder object to allow for chaining of calls to set methods
    511          */
    512         public Builder setPositiveButton(int textId, final OnClickListener listener) {
    513             P.mPositiveButtonText = P.mContext.getText(textId);
    514             P.mPositiveButtonListener = listener;
    515             return this;
    516         }
    517 
    518         /**
    519          * Set a listener to be invoked when the positive button of the dialog is pressed.
    520          * @param text The text to display in the positive button
    521          * @param listener The {@link DialogInterface.OnClickListener} to use.
    522          *
    523          * @return This Builder object to allow for chaining of calls to set methods
    524          */
    525         public Builder setPositiveButton(CharSequence text, final OnClickListener listener) {
    526             P.mPositiveButtonText = text;
    527             P.mPositiveButtonListener = listener;
    528             return this;
    529         }
    530 
    531         /**
    532          * Set a listener to be invoked when the negative button of the dialog is pressed.
    533          * @param textId The resource id of the text to display in the negative button
    534          * @param listener The {@link DialogInterface.OnClickListener} to use.
    535          *
    536          * @return This Builder object to allow for chaining of calls to set methods
    537          */
    538         public Builder setNegativeButton(int textId, final OnClickListener listener) {
    539             P.mNegativeButtonText = P.mContext.getText(textId);
    540             P.mNegativeButtonListener = listener;
    541             return this;
    542         }
    543 
    544         /**
    545          * Set a listener to be invoked when the negative button of the dialog is pressed.
    546          * @param text The text to display in the negative button
    547          * @param listener The {@link DialogInterface.OnClickListener} to use.
    548          *
    549          * @return This Builder object to allow for chaining of calls to set methods
    550          */
    551         public Builder setNegativeButton(CharSequence text, final OnClickListener listener) {
    552             P.mNegativeButtonText = text;
    553             P.mNegativeButtonListener = listener;
    554             return this;
    555         }
    556 
    557         /**
    558          * Set a listener to be invoked when the neutral button of the dialog is pressed.
    559          * @param textId The resource id of the text to display in the neutral button
    560          * @param listener The {@link DialogInterface.OnClickListener} to use.
    561          *
    562          * @return This Builder object to allow for chaining of calls to set methods
    563          */
    564         public Builder setNeutralButton(int textId, final OnClickListener listener) {
    565             P.mNeutralButtonText = P.mContext.getText(textId);
    566             P.mNeutralButtonListener = listener;
    567             return this;
    568         }
    569 
    570         /**
    571          * Set a listener to be invoked when the neutral button of the dialog is pressed.
    572          * @param text The text to display in the neutral button
    573          * @param listener The {@link DialogInterface.OnClickListener} to use.
    574          *
    575          * @return This Builder object to allow for chaining of calls to set methods
    576          */
    577         public Builder setNeutralButton(CharSequence text, final OnClickListener listener) {
    578             P.mNeutralButtonText = text;
    579             P.mNeutralButtonListener = listener;
    580             return this;
    581         }
    582 
    583         /**
    584          * Sets whether the dialog is cancelable or not.  Default is true.
    585          *
    586          * @return This Builder object to allow for chaining of calls to set methods
    587          */
    588         public Builder setCancelable(boolean cancelable) {
    589             P.mCancelable = cancelable;
    590             return this;
    591         }
    592 
    593         /**
    594          * Sets the callback that will be called if the dialog is canceled.
    595          *
    596          * <p>Even in a cancelable dialog, the dialog may be dismissed for reasons other than
    597          * being canceled or one of the supplied choices being selected.
    598          * If you are interested in listening for all cases where the dialog is dismissed
    599          * and not just when it is canceled, see
    600          * {@link #setOnDismissListener(android.content.DialogInterface.OnDismissListener) setOnDismissListener}.</p>
    601          * @see #setCancelable(boolean)
    602          * @see #setOnDismissListener(android.content.DialogInterface.OnDismissListener)
    603          *
    604          * @return This Builder object to allow for chaining of calls to set methods
    605          */
    606         public Builder setOnCancelListener(OnCancelListener onCancelListener) {
    607             P.mOnCancelListener = onCancelListener;
    608             return this;
    609         }
    610 
    611         /**
    612          * Sets the callback that will be called when the dialog is dismissed for any reason.
    613          *
    614          * @return This Builder object to allow for chaining of calls to set methods
    615          */
    616         public Builder setOnDismissListener(OnDismissListener onDismissListener) {
    617             P.mOnDismissListener = onDismissListener;
    618             return this;
    619         }
    620 
    621         /**
    622          * Sets the callback that will be called if a key is dispatched to the dialog.
    623          *
    624          * @return This Builder object to allow for chaining of calls to set methods
    625          */
    626         public Builder setOnKeyListener(OnKeyListener onKeyListener) {
    627             P.mOnKeyListener = onKeyListener;
    628             return this;
    629         }
    630 
    631         /**
    632          * Set a list of items to be displayed in the dialog as the content, you will be notified of the
    633          * selected item via the supplied listener. This should be an array type i.e. R.array.foo
    634          *
    635          * @return This Builder object to allow for chaining of calls to set methods
    636          */
    637         public Builder setItems(int itemsId, final OnClickListener listener) {
    638             P.mItems = P.mContext.getResources().getTextArray(itemsId);
    639             P.mOnClickListener = listener;
    640             return this;
    641         }
    642 
    643         /**
    644          * Set a list of items to be displayed in the dialog as the content, you will be notified of the
    645          * selected item via the supplied listener.
    646          *
    647          * @return This Builder object to allow for chaining of calls to set methods
    648          */
    649         public Builder setItems(CharSequence[] items, final OnClickListener listener) {
    650             P.mItems = items;
    651             P.mOnClickListener = listener;
    652             return this;
    653         }
    654 
    655         /**
    656          * Set a list of items, which are supplied by the given {@link ListAdapter}, to be
    657          * displayed in the dialog as the content, you will be notified of the
    658          * selected item via the supplied listener.
    659          *
    660          * @param adapter The {@link ListAdapter} to supply the list of items
    661          * @param listener The listener that will be called when an item is clicked.
    662          *
    663          * @return This Builder object to allow for chaining of calls to set methods
    664          */
    665         public Builder setAdapter(final ListAdapter adapter, final OnClickListener listener) {
    666             P.mAdapter = adapter;
    667             P.mOnClickListener = listener;
    668             return this;
    669         }
    670 
    671         /**
    672          * Set a list of items, which are supplied by the given {@link Cursor}, to be
    673          * displayed in the dialog as the content, you will be notified of the
    674          * selected item via the supplied listener.
    675          *
    676          * @param cursor The {@link Cursor} to supply the list of items
    677          * @param listener The listener that will be called when an item is clicked.
    678          * @param labelColumn The column name on the cursor containing the string to display
    679          *          in the label.
    680          *
    681          * @return This Builder object to allow for chaining of calls to set methods
    682          */
    683         public Builder setCursor(final Cursor cursor, final OnClickListener listener,
    684                 String labelColumn) {
    685             P.mCursor = cursor;
    686             P.mLabelColumn = labelColumn;
    687             P.mOnClickListener = listener;
    688             return this;
    689         }
    690 
    691         /**
    692          * Set a list of items to be displayed in the dialog as the content,
    693          * you will be notified of the selected item via the supplied listener.
    694          * This should be an array type, e.g. R.array.foo. The list will have
    695          * a check mark displayed to the right of the text for each checked
    696          * item. Clicking on an item in the list will not dismiss the dialog.
    697          * Clicking on a button will dismiss the dialog.
    698          *
    699          * @param itemsId the resource id of an array i.e. R.array.foo
    700          * @param checkedItems specifies which items are checked. It should be null in which case no
    701          *        items are checked. If non null it must be exactly the same length as the array of
    702          *        items.
    703          * @param listener notified when an item on the list is clicked. The dialog will not be
    704          *        dismissed when an item is clicked. It will only be dismissed if clicked on a
    705          *        button, if no buttons are supplied it's up to the user to dismiss the dialog.
    706          *
    707          * @return This Builder object to allow for chaining of calls to set methods
    708          */
    709         public Builder setMultiChoiceItems(int itemsId, boolean[] checkedItems,
    710                 final OnMultiChoiceClickListener listener) {
    711             P.mItems = P.mContext.getResources().getTextArray(itemsId);
    712             P.mOnCheckboxClickListener = listener;
    713             P.mCheckedItems = checkedItems;
    714             P.mIsMultiChoice = true;
    715             return this;
    716         }
    717 
    718         /**
    719          * Set a list of items to be displayed in the dialog as the content,
    720          * you will be notified of the selected item via the supplied listener.
    721          * The list will have a check mark displayed to the right of the text
    722          * for each checked item. Clicking on an item in the list will not
    723          * dismiss the dialog. Clicking on a button will dismiss the dialog.
    724          *
    725          * @param items the text of the items to be displayed in the list.
    726          * @param checkedItems specifies which items are checked. It should be null in which case no
    727          *        items are checked. If non null it must be exactly the same length as the array of
    728          *        items.
    729          * @param listener notified when an item on the list is clicked. The dialog will not be
    730          *        dismissed when an item is clicked. It will only be dismissed if clicked on a
    731          *        button, if no buttons are supplied it's up to the user to dismiss the dialog.
    732          *
    733          * @return This Builder object to allow for chaining of calls to set methods
    734          */
    735         public Builder setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems,
    736                 final OnMultiChoiceClickListener listener) {
    737             P.mItems = items;
    738             P.mOnCheckboxClickListener = listener;
    739             P.mCheckedItems = checkedItems;
    740             P.mIsMultiChoice = true;
    741             return this;
    742         }
    743 
    744         /**
    745          * Set a list of items to be displayed in the dialog as the content,
    746          * you will be notified of the selected item via the supplied listener.
    747          * The list will have a check mark displayed to the right of the text
    748          * for each checked item. Clicking on an item in the list will not
    749          * dismiss the dialog. Clicking on a button will dismiss the dialog.
    750          *
    751          * @param cursor the cursor used to provide the items.
    752          * @param isCheckedColumn specifies the column name on the cursor to use to determine
    753          *        whether a checkbox is checked or not. It must return an integer value where 1
    754          *        means checked and 0 means unchecked.
    755          * @param labelColumn The column name on the cursor containing the string to display in the
    756          *        label.
    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 setMultiChoiceItems(Cursor cursor, String isCheckedColumn, String labelColumn,
    764                 final OnMultiChoiceClickListener listener) {
    765             P.mCursor = cursor;
    766             P.mOnCheckboxClickListener = listener;
    767             P.mIsCheckedColumn = isCheckedColumn;
    768             P.mLabelColumn = labelColumn;
    769             P.mIsMultiChoice = true;
    770             return this;
    771         }
    772 
    773         /**
    774          * Set a list of items to be displayed in the dialog as the content, you will be notified of
    775          * the selected item via the supplied listener. This should be an array type i.e.
    776          * R.array.foo The list will have a check mark displayed to the right of the text for the
    777          * checked item. Clicking on an item in the list will not dismiss the dialog. Clicking on a
    778          * button will dismiss the dialog.
    779          *
    780          * @param itemsId the resource id of an array i.e. R.array.foo
    781          * @param checkedItem specifies which item is checked. If -1 no items are checked.
    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(int itemsId, int checkedItem,
    789                 final OnClickListener listener) {
    790             P.mItems = P.mContext.getResources().getTextArray(itemsId);
    791             P.mOnClickListener = listener;
    792             P.mCheckedItem = checkedItem;
    793             P.mIsSingleChoice = true;
    794             return this;
    795         }
    796 
    797         /**
    798          * Set a list of items to be displayed in the dialog as the content, you will be notified of
    799          * the selected item via the supplied listener. The list will have a check mark displayed to
    800          * the right of the text for the checked item. Clicking on an item in the list will not
    801          * dismiss the dialog. Clicking on a button will dismiss the dialog.
    802          *
    803          * @param cursor the cursor to retrieve the items from.
    804          * @param checkedItem specifies which item is checked. If -1 no items are checked.
    805          * @param labelColumn The column name on the cursor containing the string to display in the
    806          *        label.
    807          * @param listener notified when an item on the list is clicked. The dialog will not be
    808          *        dismissed when an item is clicked. It will only be dismissed if clicked on a
    809          *        button, if no buttons are supplied it's up to the user to dismiss the dialog.
    810          *
    811          * @return This Builder object to allow for chaining of calls to set methods
    812          */
    813         public Builder setSingleChoiceItems(Cursor cursor, int checkedItem, String labelColumn,
    814                 final OnClickListener listener) {
    815             P.mCursor = cursor;
    816             P.mOnClickListener = listener;
    817             P.mCheckedItem = checkedItem;
    818             P.mLabelColumn = labelColumn;
    819             P.mIsSingleChoice = true;
    820             return this;
    821         }
    822 
    823         /**
    824          * Set a list of items to be displayed in the dialog as the content, you will be notified of
    825          * the selected item via the supplied listener. The list will have a check mark displayed to
    826          * the right of the text for the checked item. Clicking on an item in the list will not
    827          * dismiss the dialog. Clicking on a button will dismiss the dialog.
    828          *
    829          * @param items the items to be displayed.
    830          * @param checkedItem specifies which item is checked. If -1 no items are checked.
    831          * @param listener notified when an item on the list is clicked. The dialog will not be
    832          *        dismissed when an item is clicked. It will only be dismissed if clicked on a
    833          *        button, if no buttons are supplied it's up to the user to dismiss the dialog.
    834          *
    835          * @return This Builder object to allow for chaining of calls to set methods
    836          */
    837         public Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, final OnClickListener listener) {
    838             P.mItems = items;
    839             P.mOnClickListener = listener;
    840             P.mCheckedItem = checkedItem;
    841             P.mIsSingleChoice = true;
    842             return this;
    843         }
    844 
    845         /**
    846          * Set a list of items to be displayed in the dialog as the content, you will be notified of
    847          * the selected item via the supplied listener. The list will have a check mark displayed to
    848          * the right of the text for the checked item. Clicking on an item in the list will not
    849          * dismiss the dialog. Clicking on a button will dismiss the dialog.
    850          *
    851          * @param adapter The {@link ListAdapter} to supply the list of items
    852          * @param checkedItem specifies which item is checked. If -1 no items are checked.
    853          * @param listener notified when an item on the list is clicked. The dialog will not be
    854          *        dismissed when an item is clicked. It will only be dismissed if clicked on a
    855          *        button, if no buttons are supplied it's up to the user to dismiss the dialog.
    856          *
    857          * @return This Builder object to allow for chaining of calls to set methods
    858          */
    859         public Builder setSingleChoiceItems(ListAdapter adapter, int checkedItem, final OnClickListener listener) {
    860             P.mAdapter = adapter;
    861             P.mOnClickListener = listener;
    862             P.mCheckedItem = checkedItem;
    863             P.mIsSingleChoice = true;
    864             return this;
    865         }
    866 
    867         /**
    868          * Sets a listener to be invoked when an item in the list is selected.
    869          *
    870          * @param listener The listener to be invoked.
    871          * @see AdapterView#setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener)
    872          *
    873          * @return This Builder object to allow for chaining of calls to set methods
    874          */
    875         public Builder setOnItemSelectedListener(final AdapterView.OnItemSelectedListener listener) {
    876             P.mOnItemSelectedListener = listener;
    877             return this;
    878         }
    879 
    880         /**
    881          * Set a custom view resource to be the contents of the Dialog. The
    882          * resource will be inflated, adding all top-level views to the screen.
    883          *
    884          * @param layoutResId Resource ID to be inflated.
    885          * @return This Builder object to allow for chaining of calls to set
    886          *         methods
    887          */
    888         public Builder setView(int layoutResId) {
    889             P.mView = null;
    890             P.mViewLayoutResId = layoutResId;
    891             P.mViewSpacingSpecified = false;
    892             return this;
    893         }
    894 
    895         /**
    896          * Set a custom view to be the contents of the Dialog. If the supplied view is an instance
    897          * of a {@link ListView} the light background will be used.
    898          *
    899          * @param view The view to use as the contents of the Dialog.
    900          *
    901          * @return This Builder object to allow for chaining of calls to set methods
    902          */
    903         public Builder setView(View view) {
    904             P.mView = view;
    905             P.mViewLayoutResId = 0;
    906             P.mViewSpacingSpecified = false;
    907             return this;
    908         }
    909 
    910         /**
    911          * Set a custom view to be the contents of the Dialog, specifying the
    912          * spacing to appear around that view. If the supplied view is an
    913          * instance of a {@link ListView} the light background will be used.
    914          *
    915          * @param view The view to use as the contents of the Dialog.
    916          * @param viewSpacingLeft Spacing between the left edge of the view and
    917          *        the dialog frame
    918          * @param viewSpacingTop Spacing between the top edge of the view and
    919          *        the dialog frame
    920          * @param viewSpacingRight Spacing between the right edge of the view
    921          *        and the dialog frame
    922          * @param viewSpacingBottom Spacing between the bottom edge of the view
    923          *        and the dialog frame
    924          * @return This Builder object to allow for chaining of calls to set
    925          *         methods
    926          *
    927          *
    928          * This is currently hidden because it seems like people should just
    929          * be able to put padding around the view.
    930          * @hide
    931          */
    932         public Builder setView(View view, int viewSpacingLeft, int viewSpacingTop,
    933                 int viewSpacingRight, int viewSpacingBottom) {
    934             P.mView = view;
    935             P.mViewLayoutResId = 0;
    936             P.mViewSpacingSpecified = true;
    937             P.mViewSpacingLeft = viewSpacingLeft;
    938             P.mViewSpacingTop = viewSpacingTop;
    939             P.mViewSpacingRight = viewSpacingRight;
    940             P.mViewSpacingBottom = viewSpacingBottom;
    941             return this;
    942         }
    943 
    944         /**
    945          * Sets the Dialog to use the inverse background, regardless of what the
    946          * contents is.
    947          *
    948          * @param useInverseBackground Whether to use the inverse background
    949          *
    950          * @return This Builder object to allow for chaining of calls to set methods
    951          */
    952         public Builder setInverseBackgroundForced(boolean useInverseBackground) {
    953             P.mForceInverseBackground = useInverseBackground;
    954             return this;
    955         }
    956 
    957         /**
    958          * @hide
    959          */
    960         public Builder setRecycleOnMeasureEnabled(boolean enabled) {
    961             P.mRecycleOnMeasure = enabled;
    962             return this;
    963         }
    964 
    965 
    966         /**
    967          * Creates a {@link AlertDialog} with the arguments supplied to this builder. It does not
    968          * {@link Dialog#show()} the dialog. This allows the user to do any extra processing
    969          * before displaying the dialog. Use {@link #show()} if you don't have any other processing
    970          * to do and want this to be created and displayed.
    971          */
    972         public AlertDialog create() {
    973             final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
    974             P.apply(dialog.mAlert);
    975             dialog.setCancelable(P.mCancelable);
    976             if (P.mCancelable) {
    977                 dialog.setCanceledOnTouchOutside(true);
    978             }
    979             dialog.setOnCancelListener(P.mOnCancelListener);
    980             dialog.setOnDismissListener(P.mOnDismissListener);
    981             if (P.mOnKeyListener != null) {
    982                 dialog.setOnKeyListener(P.mOnKeyListener);
    983             }
    984             return dialog;
    985         }
    986 
    987         /**
    988          * Creates a {@link AlertDialog} with the arguments supplied to this builder and
    989          * {@link Dialog#show()}'s the dialog.
    990          */
    991         public AlertDialog show() {
    992             AlertDialog dialog = create();
    993             dialog.show();
    994             return dialog;
    995         }
    996     }
    997 
    998 }
    999