/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.support.v7.app; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.database.Cursor; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Message; import android.support.v7.appcompat.R; import android.util.TypedValue; import android.view.ContextThemeWrapper; import android.view.KeyEvent; import android.view.View; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.Button; import android.widget.ListAdapter; import android.widget.ListView; /** * A subclass of Dialog that can display one, two or three buttons. If you only want to * display a String in this dialog box, use the setMessage() method. If you * want to display a more complex view, look up the FrameLayout called "custom" * and add your view to it: * *
* FrameLayout fl = (FrameLayout) findViewById(android.R.id.custom); * fl.addView(myView, new LayoutParams(MATCH_PARENT, WRAP_CONTENT)); ** *
The AlertDialog class takes care of automatically setting * {@link WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} for you based on whether * any views in the dialog return true from {@link View#onCheckIsTextEditor() * View.onCheckIsTextEditor()}. Generally you want this set for a Dialog * without text editors, so that it will be placed on top of the current * input method UI. You can modify this behavior by forcing the flag to your * desired mode after calling {@link #onCreate}. * *
For more information about creating dialogs, read the * Dialogs developer guide.
** Takes precedence over values set using {@link #setIcon(Drawable)}. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setIcon(int iconId) { P.mIconId = iconId; return this; } /** * Set the {@link Drawable} to be used in the title. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setIcon(Drawable icon) { P.mIcon = icon; return this; } /** * Set an icon as supplied by a theme attribute. e.g. * {@link android.R.attr#alertDialogIcon}. *
* Takes precedence over values set using {@link #setIcon(int)} or * {@link #setIcon(Drawable)}. * * @param attrId ID of a theme attribute that points to a drawable resource. */ public Builder setIconAttribute(int attrId) { TypedValue out = new TypedValue(); P.mContext.getTheme().resolveAttribute(attrId, out, true); P.mIconId = out.resourceId; return this; } /** * Set a listener to be invoked when the positive button of the dialog is pressed. * * @param textId The resource id of the text to display in the positive button * @param listener The {@link DialogInterface.OnClickListener} to use. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setPositiveButton(int textId, final OnClickListener listener) { P.mPositiveButtonText = P.mContext.getText(textId); P.mPositiveButtonListener = listener; return this; } /** * Set a listener to be invoked when the positive button of the dialog is pressed. * * @param text The text to display in the positive button * @param listener The {@link DialogInterface.OnClickListener} to use. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setPositiveButton(CharSequence text, final OnClickListener listener) { P.mPositiveButtonText = text; P.mPositiveButtonListener = listener; return this; } /** * Set a listener to be invoked when the negative button of the dialog is pressed. * * @param textId The resource id of the text to display in the negative button * @param listener The {@link DialogInterface.OnClickListener} to use. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setNegativeButton(int textId, final OnClickListener listener) { P.mNegativeButtonText = P.mContext.getText(textId); P.mNegativeButtonListener = listener; return this; } /** * Set a listener to be invoked when the negative button of the dialog is pressed. * * @param text The text to display in the negative button * @param listener The {@link DialogInterface.OnClickListener} to use. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setNegativeButton(CharSequence text, final OnClickListener listener) { P.mNegativeButtonText = text; P.mNegativeButtonListener = listener; return this; } /** * Set a listener to be invoked when the neutral button of the dialog is pressed. * * @param textId The resource id of the text to display in the neutral button * @param listener The {@link DialogInterface.OnClickListener} to use. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setNeutralButton(int textId, final OnClickListener listener) { P.mNeutralButtonText = P.mContext.getText(textId); P.mNeutralButtonListener = listener; return this; } /** * Set a listener to be invoked when the neutral button of the dialog is pressed. * * @param text The text to display in the neutral button * @param listener The {@link DialogInterface.OnClickListener} to use. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setNeutralButton(CharSequence text, final OnClickListener listener) { P.mNeutralButtonText = text; P.mNeutralButtonListener = listener; return this; } /** * Sets whether the dialog is cancelable or not. Default is true. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setCancelable(boolean cancelable) { P.mCancelable = cancelable; return this; } /** * Sets the callback that will be called if the dialog is canceled. * *
Even in a cancelable dialog, the dialog may be dismissed for reasons other than * being canceled or one of the supplied choices being selected. * If you are interested in listening for all cases where the dialog is dismissed * and not just when it is canceled, see * {@link #setOnDismissListener(android.content.DialogInterface.OnDismissListener) * setOnDismissListener}.
* * @return This Builder object to allow for chaining of calls to set methods * @see #setCancelable(boolean) * @see #setOnDismissListener(android.content.DialogInterface.OnDismissListener) */ public Builder setOnCancelListener(OnCancelListener onCancelListener) { P.mOnCancelListener = onCancelListener; return this; } /** * Sets the callback that will be called when the dialog is dismissed for any reason. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setOnDismissListener(OnDismissListener onDismissListener) { P.mOnDismissListener = onDismissListener; return this; } /** * Sets the callback that will be called if a key is dispatched to the dialog. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setOnKeyListener(OnKeyListener onKeyListener) { P.mOnKeyListener = onKeyListener; return this; } /** * Set a list of items to be displayed in the dialog as the content, you will be notified of * the * selected item via the supplied listener. This should be an array type i.e. R.array.foo * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setItems(int itemsId, final OnClickListener listener) { P.mItems = P.mContext.getResources().getTextArray(itemsId); P.mOnClickListener = listener; return this; } /** * Set a list of items to be displayed in the dialog as the content, you will be notified of * the * selected item via the supplied listener. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setItems(CharSequence[] items, final OnClickListener listener) { P.mItems = items; P.mOnClickListener = listener; return this; } /** * Set a list of items, which are supplied by the given {@link ListAdapter}, to be * displayed in the dialog as the content, you will be notified of the * selected item via the supplied listener. * * @param adapter The {@link ListAdapter} to supply the list of items * @param listener The listener that will be called when an item is clicked. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setAdapter(final ListAdapter adapter, final OnClickListener listener) { P.mAdapter = adapter; P.mOnClickListener = listener; return this; } /** * Set a list of items, which are supplied by the given {@link Cursor}, to be * displayed in the dialog as the content, you will be notified of the * selected item via the supplied listener. * * @param cursor The {@link Cursor} to supply the list of items * @param listener The listener that will be called when an item is clicked. * @param labelColumn The column name on the cursor containing the string to display * in the label. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setCursor(final Cursor cursor, final OnClickListener listener, String labelColumn) { P.mCursor = cursor; P.mLabelColumn = labelColumn; P.mOnClickListener = listener; return this; } /** * Set a list of items to be displayed in the dialog as the content, * you will be notified of the selected item via the supplied listener. * This should be an array type, e.g. R.array.foo. The list will have * a check mark displayed to the right of the text for each checked * item. Clicking on an item in the list will not dismiss the dialog. * Clicking on a button will dismiss the dialog. * * @param itemsId the resource id of an array i.e. R.array.foo * @param checkedItems specifies which items are checked. It should be null in which case * no * items are checked. If non null it must be exactly the same length as * the array of * items. * @param listener notified when an item on the list is clicked. The dialog will not be * dismissed when an item is clicked. It will only be dismissed if * clicked on a * button, if no buttons are supplied it's up to the user to dismiss the * dialog. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setMultiChoiceItems(int itemsId, boolean[] checkedItems, final OnMultiChoiceClickListener listener) { P.mItems = P.mContext.getResources().getTextArray(itemsId); P.mOnCheckboxClickListener = listener; P.mCheckedItems = checkedItems; P.mIsMultiChoice = true; return this; } /** * Set a list of items to be displayed in the dialog as the content, * you will be notified of the selected item via the supplied listener. * The list will have a check mark displayed to the right of the text * for each checked item. Clicking on an item in the list will not * dismiss the dialog. Clicking on a button will dismiss the dialog. * * @param items the text of the items to be displayed in the list. * @param checkedItems specifies which items are checked. It should be null in which case * no * items are checked. If non null it must be exactly the same length as * the array of * items. * @param listener notified when an item on the list is clicked. The dialog will not be * dismissed when an item is clicked. It will only be dismissed if * clicked on a * button, if no buttons are supplied it's up to the user to dismiss the * dialog. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, final OnMultiChoiceClickListener listener) { P.mItems = items; P.mOnCheckboxClickListener = listener; P.mCheckedItems = checkedItems; P.mIsMultiChoice = true; return this; } /** * Set a list of items to be displayed in the dialog as the content, * you will be notified of the selected item via the supplied listener. * The list will have a check mark displayed to the right of the text * for each checked item. Clicking on an item in the list will not * dismiss the dialog. Clicking on a button will dismiss the dialog. * * @param cursor the cursor used to provide the items. * @param isCheckedColumn specifies the column name on the cursor to use to determine * whether a checkbox is checked or not. It must return an integer * value where 1 * means checked and 0 means unchecked. * @param labelColumn The column name on the cursor containing the string to display in * the * label. * @param listener notified when an item on the list is clicked. The dialog will not * be * dismissed when an item is clicked. It will only be dismissed if * clicked on a * button, if no buttons are supplied it's up to the user to dismiss * the dialog. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setMultiChoiceItems(Cursor cursor, String isCheckedColumn, String labelColumn, final OnMultiChoiceClickListener listener) { P.mCursor = cursor; P.mOnCheckboxClickListener = listener; P.mIsCheckedColumn = isCheckedColumn; P.mLabelColumn = labelColumn; P.mIsMultiChoice = true; return this; } /** * Set a list of items to be displayed in the dialog as the content, you will be notified * of * the selected item via the supplied listener. This should be an array type i.e. * R.array.foo The list will have a check mark displayed to the right of the text for the * checked item. Clicking on an item in the list will not dismiss the dialog. Clicking on a * button will dismiss the dialog. * * @param itemsId the resource id of an array i.e. R.array.foo * @param checkedItem specifies which item is checked. If -1 no items are checked. * @param listener notified when an item on the list is clicked. The dialog will not be * dismissed when an item is clicked. It will only be dismissed if * clicked on a * button, if no buttons are supplied it's up to the user to dismiss the * dialog. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setSingleChoiceItems(int itemsId, int checkedItem, final OnClickListener listener) { P.mItems = P.mContext.getResources().getTextArray(itemsId); P.mOnClickListener = listener; P.mCheckedItem = checkedItem; P.mIsSingleChoice = true; return this; } /** * Set a list of items to be displayed in the dialog as the content, you will be notified * of * the selected item via the supplied listener. The list will have a check mark displayed * to * the right of the text for the checked item. Clicking on an item in the list will not * dismiss the dialog. Clicking on a button will dismiss the dialog. * * @param cursor the cursor to retrieve the items from. * @param checkedItem specifies which item is checked. If -1 no items are checked. * @param labelColumn The column name on the cursor containing the string to display in the * label. * @param listener notified when an item on the list is clicked. The dialog will not be * dismissed when an item is clicked. It will only be dismissed if * clicked on a * button, if no buttons are supplied it's up to the user to dismiss the * dialog. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setSingleChoiceItems(Cursor cursor, int checkedItem, String labelColumn, final OnClickListener listener) { P.mCursor = cursor; P.mOnClickListener = listener; P.mCheckedItem = checkedItem; P.mLabelColumn = labelColumn; P.mIsSingleChoice = true; return this; } /** * Set a list of items to be displayed in the dialog as the content, you will be notified * of * the selected item via the supplied listener. The list will have a check mark displayed * to * the right of the text for the checked item. Clicking on an item in the list will not * dismiss the dialog. Clicking on a button will dismiss the dialog. * * @param items the items to be displayed. * @param checkedItem specifies which item is checked. If -1 no items are checked. * @param listener notified when an item on the list is clicked. The dialog will not be * dismissed when an item is clicked. It will only be dismissed if * clicked on a * button, if no buttons are supplied it's up to the user to dismiss the * dialog. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, final OnClickListener listener) { P.mItems = items; P.mOnClickListener = listener; P.mCheckedItem = checkedItem; P.mIsSingleChoice = true; return this; } /** * Set a list of items to be displayed in the dialog as the content, you will be notified * of * the selected item via the supplied listener. The list will have a check mark displayed * to * the right of the text for the checked item. Clicking on an item in the list will not * dismiss the dialog. Clicking on a button will dismiss the dialog. * * @param adapter The {@link ListAdapter} to supply the list of items * @param checkedItem specifies which item is checked. If -1 no items are checked. * @param listener notified when an item on the list is clicked. The dialog will not be * dismissed when an item is clicked. It will only be dismissed if * clicked on a * button, if no buttons are supplied it's up to the user to dismiss the * dialog. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setSingleChoiceItems(ListAdapter adapter, int checkedItem, final OnClickListener listener) { P.mAdapter = adapter; P.mOnClickListener = listener; P.mCheckedItem = checkedItem; P.mIsSingleChoice = true; return this; } /** * Sets a listener to be invoked when an item in the list is selected. * * @param listener The listener to be invoked. * @return This Builder object to allow for chaining of calls to set methods * @see AdapterView#setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener) */ public Builder setOnItemSelectedListener( final AdapterView.OnItemSelectedListener listener) { P.mOnItemSelectedListener = listener; return this; } /** * Set a custom view resource to be the contents of the Dialog. The * resource will be inflated, adding all top-level views to the screen. * * @param layoutResId Resource ID to be inflated. * @return This Builder object to allow for chaining of calls to set * methods */ public Builder setView(int layoutResId) { P.mView = null; P.mViewLayoutResId = layoutResId; P.mViewSpacingSpecified = false; return this; } /** * Set a custom view to be the contents of the Dialog. If the supplied view is an instance * of a {@link ListView} the light background will be used. * * @param view The view to use as the contents of the Dialog. * @return This Builder object to allow for chaining of calls to set methods */ public Builder setView(View view) { P.mView = view; P.mViewLayoutResId = 0; P.mViewSpacingSpecified = false; return this; } /** * Set a custom view to be the contents of the Dialog, specifying the * spacing to appear around that view. If the supplied view is an * instance of a {@link ListView} the light background will be used. * * @param view The view to use as the contents of the Dialog. * @param viewSpacingLeft Spacing between the left edge of the view and * the dialog frame * @param viewSpacingTop Spacing between the top edge of the view and * the dialog frame * @param viewSpacingRight Spacing between the right edge of the view * and the dialog frame * @param viewSpacingBottom Spacing between the bottom edge of the view * and the dialog frame * @return This Builder object to allow for chaining of calls to set * methods * * * This is currently hidden because it seems like people should just * be able to put padding around the view. * @hide */ public Builder setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom) { P.mView = view; P.mViewLayoutResId = 0; P.mViewSpacingSpecified = true; P.mViewSpacingLeft = viewSpacingLeft; P.mViewSpacingTop = viewSpacingTop; P.mViewSpacingRight = viewSpacingRight; P.mViewSpacingBottom = viewSpacingBottom; return this; } /** * Sets the Dialog to use the inverse background, regardless of what the * contents is. * * @param useInverseBackground Whether to use the inverse background * @return This Builder object to allow for chaining of calls to set methods */ public Builder setInverseBackgroundForced(boolean useInverseBackground) { P.mForceInverseBackground = useInverseBackground; return this; } /** * @hide */ public Builder setRecycleOnMeasureEnabled(boolean enabled) { P.mRecycleOnMeasure = enabled; return this; } /** * Creates a {@link AlertDialog} with the arguments supplied to this builder. It does not * {@link Dialog#show()} the dialog. This allows the user to do any extra processing * before displaying the dialog. Use {@link #show()} if you don't have any other processing * to do and want this to be created and displayed. */ public AlertDialog create() { final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false); P.apply(dialog.mAlert); dialog.setCancelable(P.mCancelable); if (P.mCancelable) { dialog.setCanceledOnTouchOutside(true); } dialog.setOnCancelListener(P.mOnCancelListener); dialog.setOnDismissListener(P.mOnDismissListener); if (P.mOnKeyListener != null) { dialog.setOnKeyListener(P.mOnKeyListener); } return dialog; } /** * Creates a {@link AlertDialog} with the arguments supplied to this builder and * {@link Dialog#show()}'s the dialog. */ public AlertDialog show() { AlertDialog dialog = create(); dialog.show(); return dialog; } } }