FileDocCategorySizeDatePackage
AlertController.javaAPI DocAndroid 5.1 API42888Thu Mar 12 22:22:10 GMT 2015com.android.internal.app

AlertController

public class AlertController extends Object

Fields Summary
private final android.content.Context
mContext
private final android.content.DialogInterface
mDialogInterface
private final android.view.Window
mWindow
private CharSequence
mTitle
private CharSequence
mMessage
private android.widget.ListView
mListView
private android.view.View
mView
private int
mViewLayoutResId
private int
mViewSpacingLeft
private int
mViewSpacingTop
private int
mViewSpacingRight
private int
mViewSpacingBottom
private boolean
mViewSpacingSpecified
private android.widget.Button
mButtonPositive
private CharSequence
mButtonPositiveText
private android.os.Message
mButtonPositiveMessage
private android.widget.Button
mButtonNegative
private CharSequence
mButtonNegativeText
private android.os.Message
mButtonNegativeMessage
private android.widget.Button
mButtonNeutral
private CharSequence
mButtonNeutralText
private android.os.Message
mButtonNeutralMessage
private android.widget.ScrollView
mScrollView
private int
mIconId
private android.graphics.drawable.Drawable
mIcon
private android.widget.ImageView
mIconView
private android.widget.TextView
mTitleView
private android.widget.TextView
mMessageView
private android.view.View
mCustomTitleView
private boolean
mForceInverseBackground
private android.widget.ListAdapter
mAdapter
private int
mCheckedItem
private int
mAlertDialogLayout
private int
mButtonPanelSideLayout
private int
mListLayout
private int
mMultiChoiceItemLayout
private int
mSingleChoiceItemLayout
private int
mListItemLayout
private int
mButtonPanelLayoutHint
private android.os.Handler
mHandler
private final View.OnClickListener
mButtonHandler
Constructors Summary
public AlertController(android.content.Context context, android.content.DialogInterface di, android.view.Window window)

        mContext = context;
        mDialogInterface = di;
        mWindow = window;
        mHandler = new ButtonHandler(di);

        TypedArray a = context.obtainStyledAttributes(null,
                com.android.internal.R.styleable.AlertDialog,
                com.android.internal.R.attr.alertDialogStyle, 0);

        mAlertDialogLayout = a.getResourceId(com.android.internal.R.styleable.AlertDialog_layout,
                com.android.internal.R.layout.alert_dialog);
        mButtonPanelSideLayout = a.getResourceId(
                com.android.internal.R.styleable.AlertDialog_buttonPanelSideLayout, 0);

        mListLayout = a.getResourceId(
                com.android.internal.R.styleable.AlertDialog_listLayout,
                com.android.internal.R.layout.select_dialog);
        mMultiChoiceItemLayout = a.getResourceId(
                com.android.internal.R.styleable.AlertDialog_multiChoiceItemLayout,
                com.android.internal.R.layout.select_dialog_multichoice);
        mSingleChoiceItemLayout = a.getResourceId(
                com.android.internal.R.styleable.AlertDialog_singleChoiceItemLayout,
                com.android.internal.R.layout.select_dialog_singlechoice);
        mListItemLayout = a.getResourceId(
                com.android.internal.R.styleable.AlertDialog_listItemLayout,
                com.android.internal.R.layout.select_dialog_item);

        a.recycle();
    
Methods Summary
static booleancanTextInput(android.view.View v)

        if (v.onCheckIsTextEditor()) {
            return true;
        }

        if (!(v instanceof ViewGroup)) {
            return false;
        }

        ViewGroup vg = (ViewGroup)v;
        int i = vg.getChildCount();
        while (i > 0) {
            i--;
            v = vg.getChildAt(i);
            if (canTextInput(v)) {
                return true;
            }
        }

        return false;
    
private voidcenterButton(android.widget.Button button)

        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) button.getLayoutParams();
        params.gravity = Gravity.CENTER_HORIZONTAL;
        params.weight = 0.5f;
        button.setLayoutParams(params);
        View leftSpacer = mWindow.findViewById(R.id.leftSpacer);
        if (leftSpacer != null) {
            leftSpacer.setVisibility(View.VISIBLE);
        }
        View rightSpacer = mWindow.findViewById(R.id.rightSpacer);
        if (rightSpacer != null) {
            rightSpacer.setVisibility(View.VISIBLE);
        }
    
public android.widget.ButtongetButton(int whichButton)

        switch (whichButton) {
            case DialogInterface.BUTTON_POSITIVE:
                return mButtonPositive;
            case DialogInterface.BUTTON_NEGATIVE:
                return mButtonNegative;
            case DialogInterface.BUTTON_NEUTRAL:
                return mButtonNeutral;
            default:
                return null;
        }
    
public intgetIconAttributeResId(int attrId)

param
attrId the attributeId of the theme-specific drawable to resolve the resourceId for.
return
resId the resourceId of the theme-specific drawable

        TypedValue out = new TypedValue();
        mContext.getTheme().resolveAttribute(attrId, out, true);
        return out.resourceId;
    
public android.widget.ListViewgetListView()

        return mListView;
    
public voidinstallContent()

        /* We use a custom title so never request a window title */
        mWindow.requestFeature(Window.FEATURE_NO_TITLE);
        int contentView = selectContentView();
        mWindow.setContentView(contentView);
        setupView();
        setupDecor();
    
private static voidmanageScrollIndicators(android.view.View v, android.view.View upIndicator, android.view.View downIndicator)

        if (upIndicator != null) {
            upIndicator.setVisibility(v.canScrollVertically(-1) ? View.VISIBLE : View.INVISIBLE);
        }
        if (downIndicator != null) {
            downIndicator.setVisibility(v.canScrollVertically(1) ? View.VISIBLE : View.INVISIBLE);
        }
    
public booleanonKeyDown(int keyCode, android.view.KeyEvent event)

        return mScrollView != null && mScrollView.executeKeyEvent(event);
    
public booleanonKeyUp(int keyCode, android.view.KeyEvent event)

        return mScrollView != null && mScrollView.executeKeyEvent(event);
    
private intselectContentView()

        if (mButtonPanelSideLayout == 0) {
            return mAlertDialogLayout;
        }
        if (mButtonPanelLayoutHint == AlertDialog.LAYOUT_HINT_SIDE) {
            return mButtonPanelSideLayout;
        }
        // TODO: use layout hint side for long messages/lists
        return mAlertDialogLayout;
    
private voidsetBackground(android.content.res.TypedArray a, android.view.View topPanel, android.view.View contentPanel, android.view.View customPanel, android.view.View buttonPanel, boolean hasTitle, boolean hasCustomView, boolean hasButtons)

        int fullDark = 0;
        int topDark = 0;
        int centerDark = 0;
        int bottomDark = 0;
        int fullBright = 0;
        int topBright = 0;
        int centerBright = 0;
        int bottomBright = 0;
        int bottomMedium = 0;

        // If the needsDefaultBackgrounds attribute is set, we know we're
        // inheriting from a framework style.
        final boolean needsDefaultBackgrounds = a.getBoolean(
                R.styleable.AlertDialog_needsDefaultBackgrounds, true);
        if (needsDefaultBackgrounds) {
            fullDark = R.drawable.popup_full_dark;
            topDark = R.drawable.popup_top_dark;
            centerDark = R.drawable.popup_center_dark;
            bottomDark = R.drawable.popup_bottom_dark;
            fullBright = R.drawable.popup_full_bright;
            topBright = R.drawable.popup_top_bright;
            centerBright = R.drawable.popup_center_bright;
            bottomBright = R.drawable.popup_bottom_bright;
            bottomMedium = R.drawable.popup_bottom_medium;
        }

        topBright = a.getResourceId(R.styleable.AlertDialog_topBright, topBright);
        topDark = a.getResourceId(R.styleable.AlertDialog_topDark, topDark);
        centerBright = a.getResourceId(R.styleable.AlertDialog_centerBright, centerBright);
        centerDark = a.getResourceId(R.styleable.AlertDialog_centerDark, centerDark);

        /* We now set the background of all of the sections of the alert.
         * First collect together each section that is being displayed along
         * with whether it is on a light or dark background, then run through
         * them setting their backgrounds.  This is complicated because we need
         * to correctly use the full, top, middle, and bottom graphics depending
         * on how many views they are and where they appear.
         */

        final View[] views = new View[4];
        final boolean[] light = new boolean[4];
        View lastView = null;
        boolean lastLight = false;

        int pos = 0;
        if (hasTitle) {
            views[pos] = topPanel;
            light[pos] = false;
            pos++;
        }

        /* The contentPanel displays either a custom text message or
         * a ListView. If it's text we should use the dark background
         * for ListView we should use the light background. If neither
         * are there the contentPanel will be hidden so set it as null.
         */
        views[pos] = contentPanel.getVisibility() == View.GONE ? null : contentPanel;
        light[pos] = mListView != null;
        pos++;

        if (hasCustomView) {
            views[pos] = customPanel;
            light[pos] = mForceInverseBackground;
            pos++;
        }

        if (hasButtons) {
            views[pos] = buttonPanel;
            light[pos] = true;
        }

        boolean setView = false;
        for (pos = 0; pos < views.length; pos++) {
            final View v = views[pos];
            if (v == null) {
                continue;
            }

            if (lastView != null) {
                if (!setView) {
                    lastView.setBackgroundResource(lastLight ? topBright : topDark);
                } else {
                    lastView.setBackgroundResource(lastLight ? centerBright : centerDark);
                }
                setView = true;
            }

            lastView = v;
            lastLight = light[pos];
        }

        if (lastView != null) {
            if (setView) {
                bottomBright = a.getResourceId(R.styleable.AlertDialog_bottomBright, bottomBright);
                bottomMedium = a.getResourceId(R.styleable.AlertDialog_bottomMedium, bottomMedium);
                bottomDark = a.getResourceId(R.styleable.AlertDialog_bottomDark, bottomDark);

                // ListViews will use the Bright background, but buttons use the
                // Medium background.
                lastView.setBackgroundResource(
                        lastLight ? (hasButtons ? bottomMedium : bottomBright) : bottomDark);
            } else {
                fullBright = a.getResourceId(R.styleable.AlertDialog_fullBright, fullBright);
                fullDark = a.getResourceId(R.styleable.AlertDialog_fullDark, fullDark);

                lastView.setBackgroundResource(lastLight ? fullBright : fullDark);
            }
        }

        final ListView listView = mListView;
        if (listView != null && mAdapter != null) {
            listView.setAdapter(mAdapter);
            final int checkedItem = mCheckedItem;
            if (checkedItem > -1) {
                listView.setItemChecked(checkedItem, true);
                listView.setSelection(checkedItem);
            }
        }
    
public voidsetButton(int whichButton, java.lang.CharSequence text, DialogInterface.OnClickListener listener, android.os.Message msg)
Sets a click listener or a message to be sent when the button is clicked. You only need to pass one of {@code listener} or {@code msg}.

param
whichButton Which button, can be one of {@link DialogInterface#BUTTON_POSITIVE}, {@link DialogInterface#BUTTON_NEGATIVE}, or {@link DialogInterface#BUTTON_NEUTRAL}
param
text The text to display in positive button.
param
listener The {@link DialogInterface.OnClickListener} to use.
param
msg The {@link Message} to be sent when clicked.


        if (msg == null && listener != null) {
            msg = mHandler.obtainMessage(whichButton, listener);
        }

        switch (whichButton) {

            case DialogInterface.BUTTON_POSITIVE:
                mButtonPositiveText = text;
                mButtonPositiveMessage = msg;
                break;

            case DialogInterface.BUTTON_NEGATIVE:
                mButtonNegativeText = text;
                mButtonNegativeMessage = msg;
                break;

            case DialogInterface.BUTTON_NEUTRAL:
                mButtonNeutralText = text;
                mButtonNeutralMessage = msg;
                break;

            default:
                throw new IllegalArgumentException("Button does not exist");
        }
    
public voidsetButtonPanelLayoutHint(int layoutHint)
Sets a hint for the best button panel layout.

        mButtonPanelLayoutHint = layoutHint;
    
public voidsetCustomTitle(android.view.View customTitleView)

see
AlertDialog.Builder#setCustomTitle(View)

        mCustomTitleView = customTitleView;
    
public voidsetIcon(int resId)
Specifies the icon to display next to the alert title.

param
resId the resource identifier of the drawable to use as the icon, or 0 for no icon

        mIcon = null;
        mIconId = resId;

        if (mIconView != null) {
            if (resId != 0) {
                mIconView.setImageResource(mIconId);
            } else {
                mIconView.setVisibility(View.GONE);
            }
        }
    
public voidsetIcon(android.graphics.drawable.Drawable icon)
Specifies the icon to display next to the alert title.

param
icon the drawable to use as the icon or null for no icon

        mIcon = icon;
        mIconId = 0;

        if (mIconView != null) {
            if (icon != null) {
                mIconView.setImageDrawable(icon);
            } else {
                mIconView.setVisibility(View.GONE);
            }
        }
    
public voidsetInverseBackgroundForced(boolean forceInverseBackground)

        mForceInverseBackground = forceInverseBackground;
    
public voidsetMessage(java.lang.CharSequence message)

        mMessage = message;
        if (mMessageView != null) {
            mMessageView.setText(message);
        }
    
public voidsetTitle(java.lang.CharSequence title)

        mTitle = title;
        if (mTitleView != null) {
            mTitleView.setText(title);
        }
    
public voidsetView(android.view.View view)
Set the view to display in the dialog.

        mView = view;
        mViewLayoutResId = 0;
        mViewSpacingSpecified = false;
    
public voidsetView(android.view.View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom)
Set the view to display in the dialog along with the spacing around that view

        mView = view;
        mViewLayoutResId = 0;
        mViewSpacingSpecified = true;
        mViewSpacingLeft = viewSpacingLeft;
        mViewSpacingTop = viewSpacingTop;
        mViewSpacingRight = viewSpacingRight;
        mViewSpacingBottom = viewSpacingBottom;
    
public voidsetView(int layoutResId)
Set the view resource to display in the dialog.

        mView = null;
        mViewLayoutResId = layoutResId;
        mViewSpacingSpecified = false;
    
private booleansetupButtons()

        int BIT_BUTTON_POSITIVE = 1;
        int BIT_BUTTON_NEGATIVE = 2;
        int BIT_BUTTON_NEUTRAL = 4;
        int whichButtons = 0;
        mButtonPositive = (Button) mWindow.findViewById(R.id.button1);
        mButtonPositive.setOnClickListener(mButtonHandler);

        if (TextUtils.isEmpty(mButtonPositiveText)) {
            mButtonPositive.setVisibility(View.GONE);
        } else {
            mButtonPositive.setText(mButtonPositiveText);
            mButtonPositive.setVisibility(View.VISIBLE);
            whichButtons = whichButtons | BIT_BUTTON_POSITIVE;
        }

        mButtonNegative = (Button) mWindow.findViewById(R.id.button2);
        mButtonNegative.setOnClickListener(mButtonHandler);

        if (TextUtils.isEmpty(mButtonNegativeText)) {
            mButtonNegative.setVisibility(View.GONE);
        } else {
            mButtonNegative.setText(mButtonNegativeText);
            mButtonNegative.setVisibility(View.VISIBLE);

            whichButtons = whichButtons | BIT_BUTTON_NEGATIVE;
        }

        mButtonNeutral = (Button) mWindow.findViewById(R.id.button3);
        mButtonNeutral.setOnClickListener(mButtonHandler);

        if (TextUtils.isEmpty(mButtonNeutralText)) {
            mButtonNeutral.setVisibility(View.GONE);
        } else {
            mButtonNeutral.setText(mButtonNeutralText);
            mButtonNeutral.setVisibility(View.VISIBLE);

            whichButtons = whichButtons | BIT_BUTTON_NEUTRAL;
        }

        if (shouldCenterSingleButton(mContext)) {
            /*
             * If we only have 1 button it should be centered on the layout and
             * expand to fill 50% of the available space.
             */
            if (whichButtons == BIT_BUTTON_POSITIVE) {
                centerButton(mButtonPositive);
            } else if (whichButtons == BIT_BUTTON_NEGATIVE) {
                centerButton(mButtonNegative);
            } else if (whichButtons == BIT_BUTTON_NEUTRAL) {
                centerButton(mButtonNeutral);
            }
        }

        return whichButtons != 0;
    
private voidsetupContent(android.view.ViewGroup contentPanel)

        mScrollView = (ScrollView) mWindow.findViewById(R.id.scrollView);
        mScrollView.setFocusable(false);

        // Special case for users that only want to display a String
        mMessageView = (TextView) mWindow.findViewById(R.id.message);
        if (mMessageView == null) {
            return;
        }

        if (mMessage != null) {
            mMessageView.setText(mMessage);
        } else {
            mMessageView.setVisibility(View.GONE);
            mScrollView.removeView(mMessageView);

            if (mListView != null) {
                final ViewGroup scrollParent = (ViewGroup) mScrollView.getParent();
                final int childIndex = scrollParent.indexOfChild(mScrollView);
                scrollParent.removeViewAt(childIndex);
                scrollParent.addView(mListView, childIndex,
                        new LayoutParams(MATCH_PARENT, MATCH_PARENT));
            } else {
                contentPanel.setVisibility(View.GONE);
            }
        }

        // Set up scroll indicators (if present).
        final View indicatorUp = mWindow.findViewById(R.id.scrollIndicatorUp);
        final View indicatorDown = mWindow.findViewById(R.id.scrollIndicatorDown);
        if (indicatorUp != null || indicatorDown != null) {
            if (mMessage != null) {
                // We're just showing the ScrollView, set up listener.
                mScrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
                        @Override
                        public void onScrollChange(View v, int scrollX, int scrollY,
                                int oldScrollX, int oldScrollY) {
                            manageScrollIndicators(v, indicatorUp, indicatorDown);
                        }
                    });
                // Set up the indicators following layout.
                mScrollView.post(new Runnable() {
                     @Override
                     public void run() {
                             manageScrollIndicators(mScrollView, indicatorUp, indicatorDown);
                         }
                     });

            } else if (mListView != null) {
                // We're just showing the AbsListView, set up listener.
                mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
                        @Override
                        public void onScrollStateChanged(AbsListView view, int scrollState) {
                            // That's cool, I guess?
                        }

                        @Override
                        public void onScroll(AbsListView v, int firstVisibleItem,
                                int visibleItemCount, int totalItemCount) {
                            manageScrollIndicators(v, indicatorUp, indicatorDown);
                        }
                    });
                // Set up the indicators following layout.
                mListView.post(new Runnable() {
                        @Override
                        public void run() {
                            manageScrollIndicators(mListView, indicatorUp, indicatorDown);
                        }
                    });
            } else {
                // We don't have any content to scroll, remove the indicators.
                if (indicatorUp != null) {
                    contentPanel.removeView(indicatorUp);
                }
                if (indicatorDown != null) {
                    contentPanel.removeView(indicatorDown);
                }
            }
        }
    
private voidsetupDecor()

        final View decor = mWindow.getDecorView();
        final View parent = mWindow.findViewById(R.id.parentPanel);
        if (parent != null && decor != null) {
            decor.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
                @Override
                public WindowInsets onApplyWindowInsets(View view, WindowInsets insets) {
                    if (insets.isRound()) {
                        // TODO: Get the padding as a function of the window size.
                        int roundOffset = mContext.getResources().getDimensionPixelOffset(
                                R.dimen.alert_dialog_round_padding);
                        parent.setPadding(roundOffset, roundOffset, roundOffset, roundOffset);
                    }
                    return insets.consumeSystemWindowInsets();
                }
            });
            decor.setFitsSystemWindows(true);
            decor.requestApplyInsets();
        }
    
private booleansetupTitle(android.view.ViewGroup topPanel)

        boolean hasTitle = true;

        if (mCustomTitleView != null) {
            // Add the custom title view directly to the topPanel layout
            LayoutParams lp = new LayoutParams(
                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

            topPanel.addView(mCustomTitleView, 0, lp);

            // Hide the title template
            View titleTemplate = mWindow.findViewById(R.id.title_template);
            titleTemplate.setVisibility(View.GONE);
        } else {
            mIconView = (ImageView) mWindow.findViewById(R.id.icon);

            final boolean hasTextTitle = !TextUtils.isEmpty(mTitle);
            if (hasTextTitle) {
                // Display the title if a title is supplied, else hide it.
                mTitleView = (TextView) mWindow.findViewById(R.id.alertTitle);
                mTitleView.setText(mTitle);

                // Do this last so that if the user has supplied any icons we
                // use them instead of the default ones. If the user has
                // specified 0 then make it disappear.
                if (mIconId != 0) {
                    mIconView.setImageResource(mIconId);
                } else if (mIcon != null) {
                    mIconView.setImageDrawable(mIcon);
                } else {
                    // Apply the padding from the icon to ensure the title is
                    // aligned correctly.
                    mTitleView.setPadding(mIconView.getPaddingLeft(),
                            mIconView.getPaddingTop(),
                            mIconView.getPaddingRight(),
                            mIconView.getPaddingBottom());
                    mIconView.setVisibility(View.GONE);
                }
            } else {
                // Hide the title template
                final View titleTemplate = mWindow.findViewById(R.id.title_template);
                titleTemplate.setVisibility(View.GONE);
                mIconView.setVisibility(View.GONE);
                topPanel.setVisibility(View.GONE);
                hasTitle = false;
            }
        }
        return hasTitle;
    
private voidsetupView()

        final ViewGroup contentPanel = (ViewGroup) mWindow.findViewById(R.id.contentPanel);
        setupContent(contentPanel);
        final boolean hasButtons = setupButtons();

        final ViewGroup topPanel = (ViewGroup) mWindow.findViewById(R.id.topPanel);
        final TypedArray a = mContext.obtainStyledAttributes(
                null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);
        final boolean hasTitle = setupTitle(topPanel);

        final View buttonPanel = mWindow.findViewById(R.id.buttonPanel);
        if (!hasButtons) {
            buttonPanel.setVisibility(View.GONE);
            final View spacer = mWindow.findViewById(R.id.textSpacerNoButtons);
            if (spacer != null) {
                spacer.setVisibility(View.VISIBLE);
            }
            mWindow.setCloseOnTouchOutsideIfNotSet(true);
        }

        final FrameLayout customPanel = (FrameLayout) mWindow.findViewById(R.id.customPanel);
        final View customView;
        if (mView != null) {
            customView = mView;
        } else if (mViewLayoutResId != 0) {
            final LayoutInflater inflater = LayoutInflater.from(mContext);
            customView = inflater.inflate(mViewLayoutResId, customPanel, false);
        } else {
            customView = null;
        }

        final boolean hasCustomView = customView != null;
        if (!hasCustomView || !canTextInput(customView)) {
            mWindow.setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
        }

        if (hasCustomView) {
            final FrameLayout custom = (FrameLayout) mWindow.findViewById(R.id.custom);
            custom.addView(customView, new LayoutParams(MATCH_PARENT, MATCH_PARENT));

            if (mViewSpacingSpecified) {
                custom.setPadding(
                        mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight, mViewSpacingBottom);
            }

            if (mListView != null) {
                ((LinearLayout.LayoutParams) customPanel.getLayoutParams()).weight = 0;
            }
        } else {
            customPanel.setVisibility(View.GONE);
        }

        // Only display the divider if we have a title and a custom view or a
        // message.
        if (hasTitle) {
            final View divider;
            if (mMessage != null || customView != null || mListView != null) {
                divider = mWindow.findViewById(R.id.titleDivider);
            } else {
                divider = mWindow.findViewById(R.id.titleDividerTop);
            }

            if (divider != null) {
                divider.setVisibility(View.VISIBLE);
            }
        }

        setBackground(a, topPanel, contentPanel, customPanel, buttonPanel, hasTitle, hasCustomView,
                hasButtons);
        a.recycle();
    
private static booleanshouldCenterSingleButton(android.content.Context context)

        TypedValue outValue = new TypedValue();
        context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogCenterButtons,
                outValue, true);
        return outValue.data != 0;