Java tutorial
/* * Copyright 2014 Soichiro Kashima * * 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 com.simplealertdialog; import android.annotation.TargetApi; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.text.InputType; import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckedTextView; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; /** * <p>Dialog managed by {@link com.simplealertdialog.SimpleAlertDialogFragment} * or {@link com.simplealertdialog.SimpleAlertDialogSupportFragment}.<br/> * When you use this dialog, create {@code DialogFragment} by * {@link com.simplealertdialog.SimpleAlertDialogFragment.Builder} or * {@link com.simplealertdialog.SimpleAlertDialogSupportFragment.Builder}, * and manage it with {@code FragmentManager}.<br/> * Do not instantiate or use this class directly.</p> * <p>Basic usage for {@code android.app.Fragment}:</p> * <pre> new SimpleAlertDialogFragment.Builder() * .setMessage("Hello world!") * .setPositiveButton(android.R.string.ok) * .create().show(getFragmentManager(), "dialog");</pre> * <p>Basic usage for {@code android.support.v4.app.Fragment}:</p> * <pre> new SimpleAlertDialogSupportFragment.Builder() * .setMessage("Hello world!") * .setPositiveButton(android.R.string.ok) * .create().show(getSupportFragmentManager(), "dialog");</pre> * * @author Soichiro Kashima */ public class SimpleAlertDialog extends Dialog { /** * Listener for click events of dialog buttons.<br/> * There is no {@code setListener()} method to make these callbacks to be called.<br/> * If the caller {@code Activity} or {@code Fragment} implements this interface, * {@linkplain com.simplealertdialog.SimpleAlertDialog} will * automatically call back. */ public static interface OnClickListener { /** * Called when the positive button is clicked.<br/> * Note that all of the click events from the {@linkplain com.simplealertdialog.SimpleAlertDialog} * will be sent to this method, so you should set {@code requestCode} * to distinguish each dialogs. * * @param dialog Dialog that own this click event * @param requestCode Request code set to distinguish dialogs * @param view View of the dialog */ void onDialogPositiveButtonClicked(final SimpleAlertDialog dialog, final int requestCode, final View view); /** * Called when the negative button is clicked.<br/> * Note that all of the click events from the {@linkplain com.simplealertdialog.SimpleAlertDialog} * will be sent to this method, so you should set {@code requestCode} * to distinguish each dialogs. * * @param dialog Dialog that own this click event * @param requestCode Request code set to distinguish dialogs * @param view View of the dialog */ void onDialogNegativeButtonClicked(final SimpleAlertDialog dialog, final int requestCode, final View view); } /** * Listener for click events of dialog buttons.<br/> * There is no {@code setListener()} method to make these callbacks to be called.<br/> * If the caller {@code Activity} or {@code Fragment} implements this interface, * {@linkplain com.simplealertdialog.SimpleAlertDialog} will * automatically call back. */ public static interface OnNeutralButtonClickListener { /** * Called when the neutral button is clicked.<br/> * Note that all of the click events from the {@linkplain com.simplealertdialog.SimpleAlertDialog} * will be sent to this method, so you should set {@code requestCode} * to distinguish each dialogs. * * @param dialog Dialog that own this click event * @param requestCode Request code set to distinguish dialogs * @param view View of the dialog */ void onDialogNeutralButtonClicked(final SimpleAlertDialog dialog, final int requestCode, final View view); } /** * Listener for cancel events of dialog.<br/> * There is no {@code setListener()} method to make these callbacks to be called.<br/> * If the caller {@code Activity} or {@code Fragment} implements this interface, * {@linkplain com.simplealertdialog.SimpleAlertDialog} will * automatically call back. */ public static interface OnCancelListener { /** * Called when the dialog is canceled.<br/> * Note that all of the cancel events from the {@linkplain com.simplealertdialog.SimpleAlertDialog} * will be sent to this method, so you should set {@code requestCode} * to distinguish each dialogs. * * @param dialog Dialog that own this cancel event * @param requestCode Request code set to distinguish dialogs * @param view View of the dialog */ void onDialogCancel(final SimpleAlertDialog dialog, final int requestCode, final View view); } /** * Listener for item click events of dialog.<br/> * There is no {@code setListener()} method to make these callbacks to be called.<br/> * If the caller {@code Activity} or {@code Fragment} implements this interface * and {@code setItems()} method of builder is called, * {@linkplain com.simplealertdialog.SimpleAlertDialog} will * automatically call back.<br/> */ public static interface OnItemClickListener { /** * Called when the negative button is clicked.<br/> * Note that all of the click events from the {@linkplain com.simplealertdialog.SimpleAlertDialog} * will be sent to this method, so you should set {@code requestCode} * to distinguish each dialogs. * * @param dialog Dialog that own this click event * @param requestCode Request code set to distinguish dialogs * @param which Selected item index that begins from 0 */ void onItemClick(final SimpleAlertDialog dialog, final int requestCode, final int which); } /** * Providing the custom view of the dialog.<br/> * Use {@code setUseView()} to indicate that the dialog has a custom view.<br/> * If the {@code setUseView()} is set to {@code true} and the caller * {@code Activity} or {@code Fragment} implements this interface, * {@linkplain com.simplealertdialog.SimpleAlertDialog} will * automatically call back. */ public static interface ViewProvider { /** * Called when the dialog is created to show custom view.<br/> * Note that all of the view creation events from the * {@linkplain com.simplealertdialog.SimpleAlertDialog} * will be sent to this method, so you should set {@code requestCode} * to distinguish each dialogs. * * @param dialog Dialog that own this view creation event * @param requestCode Request code set to distinguish dialogs */ View onCreateView(final SimpleAlertDialog dialog, final int requestCode); } /** * Providing the custom {@code ListAdapter} of the dialog.<br/> * Use {@code setUseAdapter()} to indicate that the dialog has a custom adapter.<br/> * If the {@code setUseAdapter()} is set to {@code true} and the caller * {@code Activity} or {@code Fragment} implements this interface, * {@linkplain com.simplealertdialog.SimpleAlertDialog} will * automatically call back. */ public static interface ListProvider { /** * Called when the dialog is created to show custom list.<br/> * Note that all of the list creation events from the * {@linkplain com.simplealertdialog.SimpleAlertDialog} * will be sent to this method, so you should set {@code requestCode} * to distinguish each dialogs. * * @param dialog Dialog that own this list creation event * @param requestCode Request code set to distinguish dialogs * @return Custom list adapter */ ListAdapter onCreateList(final SimpleAlertDialog dialog, final int requestCode); /** * Called when the item in the custom adapter is clicked.<br/> * Note that all of the view creation events from the * {@linkplain com.simplealertdialog.SimpleAlertDialog} * will be sent to this method, so you should set {@code requestCode} * to distinguish each dialogs. * * @param dialog Dialog that own this click event * @param requestCode Request code set to distinguish dialogs * @param position Position of the list items (from 0) */ void onListItemClick(final SimpleAlertDialog dialog, final int requestCode, final int position); } /** * Providing the custom {@code SingleChoice} list of the dialog.<br/> * Use {@code setSingleChoiceCheckedItem()} to indicate that the dialog * has a single choice item list.<br/> * If the {@code setSingleChoiceCheckedItem()} is set to {@code true} * and the caller {@code Activity} or {@code Fragment} implements this interface, * {@linkplain com.simplealertdialog.SimpleAlertDialog} will * automatically call back. */ public static interface SingleChoiceArrayItemProvider { /** * Called when the single choice items are created.<br/> * Note that all of the creation events of the single choice items from the * {@linkplain com.simplealertdialog.SimpleAlertDialog} * will be sent to this method, so you should set {@code requestCode} * to distinguish each dialogs. * * @param dialog Dialog that own single choice items creation event * @param requestCode Request code set to distinguish dialogs * @return Char sequences of the single choice items */ CharSequence[] onCreateSingleChoiceArray(final SimpleAlertDialog dialog, final int requestCode); /** * Called when the item in the custom single choice items is clicked.<br/> * Note that all of the view creation events from the * {@linkplain com.simplealertdialog.SimpleAlertDialog} * will be sent to this method, so you should set {@code requestCode} * to distinguish each dialogs. * * @param dialog Dialog that own this click event * @param requestCode Request code set to distinguish dialogs * @param position Position of the list items (from 0) */ void onSingleChoiceArrayItemClick(final SimpleAlertDialog dialog, final int requestCode, final int position); } private class IconListItem { public int iconResId; public CharSequence text; public IconListItem(final int iconResId, CharSequence text) { this.iconResId = iconResId; this.text = text; } } static final String ARG_THEME_RES_ID = "argThemeResId"; static final String ARG_TITLE = "argTitle"; static final String ARG_TITLE_RES_ID = "argTitleResId"; static final String ARG_ICON = "argIcon"; static final String ARG_MESSAGE = "argMessage"; static final String ARG_MESSAGE_RES_ID = "argMessageResId"; static final String ARG_POSITIVE_BUTTON = "argPositiveButton"; static final String ARG_POSITIVE_BUTTON_RES_ID = "argPositiveButtonResId"; static final String ARG_NEUTRAL_BUTTON = "argNeutralButton"; static final String ARG_NEUTRAL_BUTTON_RES_ID = "argNeutralButtonResId"; static final String ARG_NEGATIVE_BUTTON = "argNegativeButton"; static final String ARG_NEGATIVE_BUTTON_RES_ID = "argNegativeButtonResId"; static final String ARG_ITEMS = "argItems"; static final String ARG_ITEMS_RES_ID = "argItemsResId"; static final String ARG_ICONS = "argIcons"; static final String ARG_REQUEST_CODE = "argRequestCode"; static final String ARG_CANCELABLE = "argCancelable"; static final String ARG_CANCELED_ON_TOUCH_OUTSIDE = "argCanceledOnTouchOutside"; static final String ARG_SINGLE_CHOICE_CHECKED_ITEM = "argSingleChoiceCheckedItem"; static final String ARG_USE_VIEW = "argUseView"; static final String ARG_EDIT_TEXT_INITIAL_TEXT = "argEditTextInitialText"; static final String ARG_EDIT_TEXT_INPUT_TYPE = "argEditTextInputType"; static final String ARG_USE_ADAPTER = "argUseAdapter"; private CharSequence mMessage; private CharSequence mTitle; private int mIcon; private CharSequence mPositiveButtonText; private CharSequence mNeutralButtonText; private CharSequence mNegativeButtonText; private DialogInterface.OnClickListener mPositiveButtonListener; private DialogInterface.OnClickListener mNeutralButtonListener; private DialogInterface.OnClickListener mNegativeButtonListener; private View mView; private ListAdapter mAdapter; private boolean mSingleChoice = true; private int mCheckedItem; private AdapterView.OnItemClickListener mListItemListener; private int mListChoiceIndicatorSingle; private int mTitleTextStyle; private int mMessageTextStyle; private int mButtonTextStyle; private int mListItemTextStyle; private Drawable mListSelectorBackground; private Drawable mTitleSeparatorBackground; private int mTitleSeparatorHeight; private Drawable mButtonTopDividerBackground; private Drawable mButtonVerticalDividerBackground; private Drawable mBackgroundFull; private Drawable mBackgroundTop; private Drawable mBackgroundMiddle; private Drawable mBackgroundBottom; /** * Creates the new dialog.<br/> * Users should not directly call this. * * @param context Dialog owner context * @param themeResId Dialog theme resource ID */ public SimpleAlertDialog(Context context, int themeResId) { super(context, themeResId); obtainStyles(); } /** * Creates the new dialog.<br/> * Users should not directly call this. * * @param context Dialog owner context */ public SimpleAlertDialog(Context context) { super(context); obtainStyles(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(android.view.Window.FEATURE_NO_TITLE); setContentView(R.layout.sad__dialog_simple); getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT)); // Background setBackground(R.id.header, mBackgroundTop); setBackground(R.id.bar_wrapper, mBackgroundMiddle); setBackground(R.id.body, mBackgroundBottom); // Title if (TextUtils.isEmpty(mTitle)) { findViewById(R.id.header).setVisibility(View.GONE); findViewById(R.id.bar_wrapper).setVisibility(View.GONE); findViewById(R.id.title).setVisibility(View.GONE); findViewById(R.id.icon).setVisibility(View.GONE); setBackground(R.id.body, mBackgroundFull); } else { ((TextView) findViewById(R.id.title)).setText(mTitle); if (mTitleTextStyle != 0) { ((TextView) findViewById(R.id.title)).setTextAppearance(getContext(), mTitleTextStyle); } if (mIcon > 0) { ((ImageView) findViewById(R.id.icon)).setImageResource(mIcon); findViewById(R.id.title).setPadding(findViewById(R.id.title).getPaddingLeft() / 2, findViewById(R.id.title).getPaddingTop(), findViewById(R.id.title).getPaddingRight(), findViewById(R.id.title).getPaddingBottom()); } else { findViewById(R.id.icon).setVisibility(View.GONE); } setBackground(R.id.bar, mTitleSeparatorBackground); if (mTitleSeparatorHeight == 0) { mTitleSeparatorHeight = getContext().getResources() .getDimensionPixelSize(R.dimen.sad__dialog_title_separator_height); } FrameLayout.LayoutParams lpBar = new FrameLayout.LayoutParams(getMatchParent(), mTitleSeparatorHeight); findViewById(R.id.bar).setLayoutParams(lpBar); findViewById(R.id.bar).requestLayout(); LinearLayout.LayoutParams lpBarWrapper = new LinearLayout.LayoutParams(getMatchParent(), mTitleSeparatorHeight); findViewById(R.id.bar_wrapper).setLayoutParams(lpBarWrapper); findViewById(R.id.bar_wrapper).requestLayout(); } // Message if (TextUtils.isEmpty(mMessage)) { findViewById(R.id.message).setVisibility(View.GONE); } else { ((TextView) findViewById(R.id.message)).setText(mMessage); if (mMessageTextStyle != 0) { ((TextView) findViewById(R.id.message)).setTextAppearance(getContext(), mMessageTextStyle); } } // Custom View if (mView != null) { LinearLayout group = (LinearLayout) findViewById(R.id.view); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(getMatchParent(), LinearLayout.LayoutParams.WRAP_CONTENT); group.addView(mView, lp); } else { findViewById(R.id.view).setVisibility(View.GONE); } // Custom Adapter if (mAdapter != null) { ListView list = (ListView) findViewById(R.id.list); list.setAdapter(mAdapter); if (mSingleChoice) { list.setChoiceMode(ListView.CHOICE_MODE_SINGLE); } if (mSingleChoice && 0 <= mCheckedItem && mCheckedItem < mAdapter.getCount()) { list.setItemChecked(mCheckedItem, true); list.setSelectionFromTop(mCheckedItem, 0); } list.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (mListItemListener != null) { mListItemListener.onItemClick(parent, view, position, id); } dismiss(); } }); } else { findViewById(R.id.list).setVisibility(View.GONE); } // Positive Button boolean hasPositiveButton = false; if (mPositiveButtonText != null) { hasPositiveButton = true; ((TextView) findViewById(R.id.button_positive_label)).setText(mPositiveButtonText); if (mButtonTextStyle != 0) { ((TextView) findViewById(R.id.button_positive_label)).setTextAppearance(getContext(), mButtonTextStyle); } } if (mPositiveButtonListener != null) { hasPositiveButton = true; findViewById(R.id.button_positive).setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { if (mPositiveButtonListener != null) { mPositiveButtonListener.onClick(SimpleAlertDialog.this, 0); } dismiss(); } }); } if (!hasPositiveButton) { findViewById(R.id.button_positive).setVisibility(View.GONE); } // Neutral Button boolean hasNeutralButton = false; if (mNeutralButtonText != null) { hasNeutralButton = true; ((TextView) findViewById(R.id.button_neutral_label)).setText(mNeutralButtonText); if (mButtonTextStyle != 0) { ((TextView) findViewById(R.id.button_neutral_label)).setTextAppearance(getContext(), mButtonTextStyle); } } if (mNeutralButtonListener != null) { hasNeutralButton = true; findViewById(R.id.button_neutral).setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { if (mNeutralButtonListener != null) { mNeutralButtonListener.onClick(SimpleAlertDialog.this, 0); } dismiss(); } }); } if (!hasNeutralButton) { findViewById(R.id.button_neutral).setVisibility(View.GONE); } // Negative Button boolean hasNegativeButton = false; if (mNegativeButtonText != null) { hasNegativeButton = true; ((TextView) findViewById(R.id.button_negative_label)).setText(mNegativeButtonText); if (mButtonTextStyle != 0) { ((TextView) findViewById(R.id.button_negative_label)).setTextAppearance(getContext(), mButtonTextStyle); } } if (mNegativeButtonListener != null) { hasNegativeButton = true; findViewById(R.id.button_negative).setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { if (mNegativeButtonListener != null) { mNegativeButtonListener.onClick(SimpleAlertDialog.this, 1); } dismiss(); } }); } if (!hasNegativeButton) { findViewById(R.id.button_negative).setVisibility(View.GONE); } if (!hasPositiveButton && !hasNegativeButton) { findViewById(R.id.button_divider_top).setVisibility(View.GONE); findViewById(R.id.button_divider).setVisibility(View.GONE); } else if (!hasPositiveButton || !hasNegativeButton) { findViewById(R.id.button_divider).setVisibility(View.GONE); setBackground(R.id.button_divider_top, mButtonTopDividerBackground); } else { setBackground(R.id.button_divider_top, mButtonTopDividerBackground); setBackground(R.id.button_divider, mButtonVerticalDividerBackground); } if (hasNeutralButton) { setBackground(R.id.button_divider_neutral, mButtonVerticalDividerBackground); } else { findViewById(R.id.button_divider_neutral).setVisibility(View.GONE); } } public void setMessage(final CharSequence message) { if (message == null) { return; } mMessage = message; } public void setMessage(final int resId) { setMessage(getContext().getText(resId)); } @Override public void setTitle(final CharSequence title) { if (title == null) { return; } mTitle = title; } @Override public void setTitle(final int resId) { setTitle(getContext().getText(resId)); } public void setIcon(final int resId) { if (resId <= 0) { return; } mIcon = resId; } public void setView(final View view) { if (view == null) { return; } mView = view; } public View getView() { return mView; } public void setItems(final CharSequence[] items, final AdapterView.OnItemClickListener listener) { mAdapter = new ArrayAdapter<CharSequence>(getContext(), android.R.layout.simple_list_item_1, items) { @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); if (view != null) { TextView tv = (TextView) view.findViewById(android.R.id.text1); if (mListItemTextStyle != 0) { tv.setTextAppearance(getContext(), mListItemTextStyle); } tv.setText(items[position]); } return view; } }; mListItemListener = listener; } public void setItems(final CharSequence[] items, final int[] iconResIds, final AdapterView.OnItemClickListener listener) { if (iconResIds == null || items == null) { return; } final IconListItem[] iconListItems = new IconListItem[Math.min(iconResIds.length, items.length)]; for (int i = 0; i < iconResIds.length && i < items.length; i++) { iconListItems[i] = new IconListItem(iconResIds[i], items[i]); } mAdapter = new ArrayAdapter<IconListItem>(getContext(), android.R.layout.simple_list_item_1, iconListItems) { @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); if (view != null) { TextView tv = (TextView) view.findViewById(android.R.id.text1); if (mListItemTextStyle != 0) { tv.setTextAppearance(getContext(), mListItemTextStyle); } tv.setText(iconListItems[position].text); tv.setCompoundDrawablesWithIntrinsicBounds(iconListItems[position].iconResId, 0, 0, 0); int padding = (int) (8 * getContext().getResources().getDisplayMetrics().density); tv.setCompoundDrawablePadding(padding); } return view; } }; mListItemListener = listener; } public void setAdapter(final ListAdapter adapter, final AdapterView.OnItemClickListener listener) { if (adapter == null) { return; } mAdapter = adapter; mListItemListener = listener; } public void setSingleChoiceItems(final CharSequence[] items, final int checkedItem, final AdapterView.OnItemClickListener listener) { if (items == null) { return; } mAdapter = new ArrayAdapter<CharSequence>(getContext(), android.R.layout.simple_list_item_single_choice, items) { @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); if (view != null) { CheckedTextView c = (CheckedTextView) view.findViewById(android.R.id.text1); if (mListChoiceIndicatorSingle != 0) { c.setCheckMarkDrawable(mListChoiceIndicatorSingle); } if (mListItemTextStyle != 0) { c.setTextAppearance(getContext(), mListItemTextStyle); } setBackground(c, mListSelectorBackground); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { Resources res = getContext().getResources(); c.setPadding(res.getDimensionPixelSize(R.dimen.sad__simple_list_item_padding_left), 0, res.getDimensionPixelSize(R.dimen.sad__simple_list_item_padding_right), 0); } } return view; } }; mSingleChoice = true; mCheckedItem = checkedItem; mListItemListener = listener; } public void setPositiveButton(final CharSequence text, final DialogInterface.OnClickListener listener) { if (text == null) { return; } mPositiveButtonText = text; mPositiveButtonListener = listener; } public void setPositiveButton(final int resId, final DialogInterface.OnClickListener listener) { setPositiveButton(getContext().getText(resId), listener); } public void setNeutralButton(final CharSequence text, final DialogInterface.OnClickListener listener) { if (text == null) { return; } mNeutralButtonText = text; mNeutralButtonListener = listener; } public void setNeutralButton(final int resId, final DialogInterface.OnClickListener listener) { setNeutralButton(getContext().getText(resId), listener); } public void setNegativeButton(final CharSequence text, final DialogInterface.OnClickListener listener) { if (text == null) { return; } mNegativeButtonText = text; mNegativeButtonListener = listener; } public void setNegativeButton(final int resId, final DialogInterface.OnClickListener listener) { setNegativeButton(getContext().getText(resId), listener); } private void obtainStyles() { TypedArray a = getContext().getTheme().obtainStyledAttributes(null, R.styleable.SimpleAlertDialogStyle, R.attr.simpleAlertDialogStyle, R.style.Theme_SimpleAlertDialog); mListChoiceIndicatorSingle = a .getResourceId(R.styleable.SimpleAlertDialogStyle_sadListChoiceIndicatorSingle, 0); mTitleTextStyle = a.getResourceId(R.styleable.SimpleAlertDialogStyle_sadTitleTextStyle, 0); mMessageTextStyle = a.getResourceId(R.styleable.SimpleAlertDialogStyle_sadMessageTextStyle, 0); mButtonTextStyle = a.getResourceId(R.styleable.SimpleAlertDialogStyle_sadButtonTextStyle, 0); mListItemTextStyle = a.getResourceId(R.styleable.SimpleAlertDialogStyle_sadListItemTextStyle, 0); mListSelectorBackground = a.getDrawable(R.styleable.SimpleAlertDialogStyle_sadListSelectorBackground); mTitleSeparatorBackground = a.getDrawable(R.styleable.SimpleAlertDialogStyle_sadTitleSeparatorBackground); mTitleSeparatorHeight = a.getLayoutDimension(R.styleable.SimpleAlertDialogStyle_sadTitleSeparatorHeight, getContext().getResources().getDimensionPixelSize(R.dimen.sad__dialog_title_separator_height)); mButtonTopDividerBackground = a .getDrawable(R.styleable.SimpleAlertDialogStyle_sadButtonTopDividerBackground); mButtonVerticalDividerBackground = a .getDrawable(R.styleable.SimpleAlertDialogStyle_sadButtonVerticalDividerBackground); mBackgroundFull = a.getDrawable(R.styleable.SimpleAlertDialogStyle_sadBackgroundFull); mBackgroundTop = a.getDrawable(R.styleable.SimpleAlertDialogStyle_sadBackgroundTop); mBackgroundMiddle = a.getDrawable(R.styleable.SimpleAlertDialogStyle_sadBackgroundMiddle); mBackgroundBottom = a.getDrawable(R.styleable.SimpleAlertDialogStyle_sadBackgroundBottom); a.recycle(); } private void setBackground(final int resId, final Drawable d) { if (resId == 0 || d == null) { return; } View view = findViewById(resId); setBackground(view, d); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @SuppressWarnings("deprecation") private void setBackground(final View view, final Drawable d) { if (view == null || d == null) { return; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { view.setBackground(d.getConstantState().newDrawable()); } else { view.setBackgroundDrawable(d.getConstantState().newDrawable()); } } @SuppressWarnings("deprecation") private int getMatchParent() { if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ECLAIR_MR1) { return ViewGroup.LayoutParams.FILL_PARENT; } else { return ViewGroup.LayoutParams.MATCH_PARENT; } } /** * Dialog builder like {@link android.app.AlertDialog.Builder}.<br/> * To show your custom dialog, construct the dialog style with this builder, * and show with {@code FragmentManager}. * * @param <T> Type of the {@code SimpleAlertDialog} fragment * @param <F> Type of the basic {@code Fragment} */ public static abstract class Builder<T, F> { private int mThemeResId; private CharSequence mTitle; private int mTitleResId; private int mIcon; private CharSequence mMessage; private int mMessageResId; private CharSequence mPositiveButton; private int mPositiveButtonResId; private CharSequence mNeutralButton; private int mNeutralButtonResId; private CharSequence mNegativeButton; private int mNegativeButtonResId; private int mItemsResId; private CharSequence[] mItems; private int[] mIcons; private int mRequestCode; private boolean mCancelable = true; private boolean mCanceledOnTouchOutside = true; private int mSingleChoiceCheckedItem = -1; private CharSequence mEditTextInitialText; private int mEditTextInputType; private boolean mUseView; private boolean mUseAdapter; /** * Sets the theme of the dialog. * * @param resId Theme(style) resource ID * @return Builder itself */ public Builder<T, F> setTheme(final int resId) { mThemeResId = resId; return this; } /** * Sets the title of the dialog. * * @param title Title char sequence or string * @return Builder itself */ public Builder<T, F> setTitle(final CharSequence title) { mTitle = title; return this; } /** * Sets the title of the dialog. * * @param resId Title string resource ID * @return Builder itself */ public Builder<T, F> setTitle(final int resId) { mTitleResId = resId; return this; } /** * Sets the icon for the title of the dialog. * * @param resId Icon drawable resource ID * @return Builder itself */ public Builder<T, F> setIcon(final int resId) { mIcon = resId; return this; } /** * Sets the message of the dialog. * * @param message Message char sequence or string * @return Builder itself */ public Builder<T, F> setMessage(final CharSequence message) { mMessage = message; return this; } /** * Sets the message of the dialog. * * @param resId Message string resource ID * @return Builder itself */ public Builder<T, F> setMessage(final int resId) { mMessageResId = resId; return this; } /** * Sets the positive button's char sequence or string.<br/> * This also enables callback of the click event of the positive button. * * @param positiveButton Char sequence or string of the positive button * @return Builder itself */ public Builder<T, F> setPositiveButton(final CharSequence positiveButton) { mPositiveButton = positiveButton; return this; } /** * Sets the positive button's char sequence or string.<br/> * This also enables callback of the click event of the positive button. * * @param resId String resource ID of the positive button * @return Builder itself */ public Builder<T, F> setPositiveButton(final int resId) { mPositiveButtonResId = resId; return this; } /** * Sets the neutral button's char sequence or string.<br/> * This also enables callback of the click event of the neutral button. * * @param neutralButton Char sequence or string of the neutral button * @return Builder itself */ public Builder<T, F> setNeutralButton(final CharSequence neutralButton) { mNeutralButton = neutralButton; return this; } /** * Sets the neutral button's char sequence or string.<br/> * This also enables callback of the click event of the neutral button. * * @param resId String resource ID of the neutral button * @return Builder itself */ public Builder<T, F> setNeutralButton(final int resId) { mNeutralButtonResId = resId; return this; } /** * Sets the negative button's char sequence or string.<br/> * This also enables callback of the click event of the negative button. * * @param negativeButton Char sequence or string of the negative button * @return Builder itself */ public Builder<T, F> setNegativeButton(final CharSequence negativeButton) { mNegativeButton = negativeButton; return this; } /** * Sets the negative button's char sequence or string.<br/> * This also enables callback of the click event of the negative button. * * @param resId String resource ID of the negative button * @return Builder itself */ public Builder<T, F> setNegativeButton(final int resId) { mNegativeButtonResId = resId; return this; } /** * Sets the char sequence array items.<br/> * This also enables callback of the click event of the list items. * * @param items Char sequence array for items * @return Builder itself */ @TargetApi(Build.VERSION_CODES.ECLAIR) public Builder<T, F> setItems(final CharSequence[] items) { mItems = items; return this; } /** * Sets the char sequence array items.<br/> * This also enables callback of the click event of the list items. * * @param resId Char sequence array resource ID for items * @return Builder itself */ public Builder<T, F> setItems(final int resId) { mItemsResId = resId; return this; } /** * Sets the char sequence array items.<br/> * This also enables callback of the click event of the list items. * * @param items Char sequence array for items * @param icons Icon resource ID array * @return Builder itself */ @TargetApi(Build.VERSION_CODES.ECLAIR) public Builder<T, F> setItems(final CharSequence[] items, final int[] icons) { mItems = items; mIcons = icons; return this; } /** * Sets the char sequence array items.<br/> * This also enables callback of the click event of the list items. * * @param resId Char sequence array resource ID for items * @param icons Icon resource ID array * @return Builder itself */ public Builder<T, F> setItems(final int resId, final int[] icons) { mItemsResId = resId; mIcons = icons; return this; } /** * Sets the request code of the callbacks.<br/> * This code will be passed to the callbacks to distinguish * other dialogs. * * @param requestCode Request code * @return Builder itself */ public Builder<T, F> setRequestCode(final int requestCode) { mRequestCode = requestCode; return this; } /** * Sets the dialog to be cancelable or not.<br/> * Default value is {@code true}.<br/> * If you set this to {@code false}, pressing back button * and touching outside of the dialog don't cancel the dialog. * * @param cancelable {@code true} if the dialog is cancelable * @return Builder itself */ public Builder<T, F> setCancelable(final boolean cancelable) { mCancelable = cancelable; return this; } /** * Sets the dialog to be cancelable on touching outside of the dialog.<br/> * Default value is {@code true}. * * @param canceledOnTouchOutside {@code true} if the dialog should be canceled on touch outside * @return Builder itself */ public Builder<T, F> setCanceledOnTouchOutside(final boolean canceledOnTouchOutside) { mCanceledOnTouchOutside = canceledOnTouchOutside; return this; } /** * Sets the default checked item of the single choice items.<br/> * This also enables callback of the * {@link com.simplealertdialog.SimpleAlertDialog.SingleChoiceArrayItemProvider}. * * @param checkedItem Position of the checked item * @return Builder itself */ public Builder<T, F> setSingleChoiceCheckedItem(final int checkedItem) { mSingleChoiceCheckedItem = checkedItem; return this; } /** * Sets the dialog to use {@code EditText} widget.<br/> * Same as {@code setEditText(initialText, InputType.TYPE_CLASS_TEXT)}. * * @param initialText initial value of the {@code EditText} * @return Builder itself */ public Builder<T, F> setEditText(final CharSequence initialText) { mEditTextInitialText = initialText; mEditTextInputType = InputType.TYPE_CLASS_TEXT; return this; } /** * Sets the dialog to use {@code EditText} widget. * * @param initialText initial value of the {@code EditText} * @param inputType input types of the {@code EditText} defined in {@linkplain android.text.InputType} * @return Builder itself */ public Builder<T, F> setEditText(final CharSequence initialText, final int inputType) { mEditTextInitialText = initialText; mEditTextInputType = inputType; return this; } /** * Sets the dialog to use custom view provided by * {@link com.simplealertdialog.SimpleAlertDialog.ViewProvider}. * * @param useView {@code true} if you provide a custom view for this dialog * @return Builder itself */ public Builder<T, F> setUseView(final boolean useView) { mUseView = useView; return this; } /** * Sets the dialog to use custom {@code ListProvider} provided by * {@link com.simplealertdialog.SimpleAlertDialog.ListProvider}. * * @param useAdapter {@code true} if you provide a custom adapter for this dialog * @return Builder itself */ public Builder<T, F> setUseAdapter(final boolean useAdapter) { mUseAdapter = useAdapter; return this; } /** * Creates the arguments of the {@code SimpleAlertDialog} as a {@code Bundle}.<br/> * In most cases, you don't have to call this method directly. * * @return Created arguments bundle */ @TargetApi(Build.VERSION_CODES.FROYO) public Bundle createArguments() { Bundle args = new Bundle(); if (mThemeResId > 0) { args.putInt(SimpleAlertDialog.ARG_THEME_RES_ID, mThemeResId); } if (mTitle != null) { args.putCharSequence(SimpleAlertDialog.ARG_TITLE, mTitle); } else if (mTitleResId > 0) { args.putInt(SimpleAlertDialog.ARG_TITLE_RES_ID, mTitleResId); } if (mIcon > 0) { args.putInt(SimpleAlertDialog.ARG_ICON, mIcon); } if (mMessage != null) { args.putCharSequence(SimpleAlertDialog.ARG_MESSAGE, mMessage); } else if (mMessageResId > 0) { args.putInt(SimpleAlertDialog.ARG_MESSAGE_RES_ID, mMessageResId); } if (mPositiveButton != null) { args.putCharSequence(SimpleAlertDialog.ARG_POSITIVE_BUTTON, mPositiveButton); } else if (mPositiveButtonResId > 0) { args.putInt(SimpleAlertDialog.ARG_POSITIVE_BUTTON_RES_ID, mPositiveButtonResId); } if (mNeutralButton != null) { args.putCharSequence(SimpleAlertDialog.ARG_NEUTRAL_BUTTON, mNeutralButton); } else if (mNeutralButtonResId > 0) { args.putInt(SimpleAlertDialog.ARG_NEUTRAL_BUTTON_RES_ID, mNeutralButtonResId); } if (mNegativeButton != null) { args.putCharSequence(SimpleAlertDialog.ARG_NEGATIVE_BUTTON, mNegativeButton); } else if (mNegativeButtonResId > 0) { args.putInt(SimpleAlertDialog.ARG_NEGATIVE_BUTTON_RES_ID, mNegativeButtonResId); } if (mItems != null && Build.VERSION_CODES.ECLAIR <= Build.VERSION.SDK_INT) { args.putCharSequenceArray(SimpleAlertDialog.ARG_ITEMS, mItems); } else if (mItemsResId > 0) { args.putInt(SimpleAlertDialog.ARG_ITEMS_RES_ID, mItemsResId); } if (mIcons != null) { args.putIntArray(SimpleAlertDialog.ARG_ICONS, mIcons); } args.putBoolean(SimpleAlertDialog.ARG_CANCELABLE, mCancelable); args.putBoolean(SimpleAlertDialog.ARG_CANCELED_ON_TOUCH_OUTSIDE, mCanceledOnTouchOutside); if (mSingleChoiceCheckedItem >= 0) { args.putInt(SimpleAlertDialog.ARG_SINGLE_CHOICE_CHECKED_ITEM, mSingleChoiceCheckedItem); } if (mEditTextInitialText != null || 0 < mEditTextInputType) { args.putCharSequence(SimpleAlertDialog.ARG_EDIT_TEXT_INITIAL_TEXT, mEditTextInitialText); args.putInt(SimpleAlertDialog.ARG_EDIT_TEXT_INPUT_TYPE, mEditTextInputType); } args.putBoolean(SimpleAlertDialog.ARG_USE_VIEW, mUseView); args.putBoolean(SimpleAlertDialog.ARG_USE_ADAPTER, mUseAdapter); args.putInt(SimpleAlertDialog.ARG_REQUEST_CODE, mRequestCode); return args; } /** * Sets the target fragment of this {@code DialogFragment}.<br/> * Use this method to tell the dialog that {@code fragment} of the argument * is the callback instance for some of the events of dialogs. * * @param fragment Target fragment instance * @return Builder itself */ public abstract Builder<T, F> setTargetFragment(F fragment); /** * Creates the new dialog instance with styles set by this builder. * * @return dialog instance */ public abstract T create(); } }