AlertController.java revision 58c14e5c83aa8f836aff6e48ad90e6976948f1ac
119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes/*
219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes * Copyright (C) 2015 The Android Open Source Project
319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes *
419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes * Licensed under the Apache License, Version 2.0 (the "License");
519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes * you may not use this file except in compliance with the License.
619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes * You may obtain a copy of the License at
719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes *
819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes *      http://www.apache.org/licenses/LICENSE-2.0
919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes *
1019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes * Unless required by applicable law or agreed to in writing, software
1119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes * distributed under the License is distributed on an "AS IS" BASIS,
1219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes * See the License for the specific language governing permissions and
1419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes * limitations under the License.
1519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes */
1619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
1719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banespackage android.support.v7.app;
1819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
1919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.content.Context;
2019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.content.DialogInterface;
2119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.content.res.TypedArray;
2219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.database.Cursor;
2319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.graphics.drawable.Drawable;
24cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banesimport android.os.Build;
2519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.os.Handler;
2619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.os.Message;
27cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banesimport android.support.annotation.Nullable;
28cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banesimport android.support.v4.view.ViewCompat;
29cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banesimport android.support.v4.widget.NestedScrollView;
3019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.support.v7.appcompat.R;
3119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.text.TextUtils;
3219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.util.TypedValue;
3319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.view.KeyEvent;
3419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.view.LayoutInflater;
3519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.view.View;
3619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.view.ViewGroup;
3719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.view.ViewGroup.LayoutParams;
38cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banesimport android.view.ViewParent;
39cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banesimport android.view.ViewStub;
4019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.view.Window;
4119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.view.WindowManager;
42cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banesimport android.widget.AbsListView;
4319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.widget.AdapterView;
4419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.widget.AdapterView.OnItemClickListener;
4519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.widget.ArrayAdapter;
4619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.widget.Button;
4719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.widget.CheckedTextView;
4819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.widget.CursorAdapter;
4919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.widget.FrameLayout;
5019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.widget.ImageView;
5119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.widget.LinearLayout;
5219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.widget.ListAdapter;
5319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.widget.ListView;
5419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.widget.SimpleCursorAdapter;
5519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport android.widget.TextView;
5619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
5719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport java.lang.ref.WeakReference;
5819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
5919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesimport static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
6019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
6119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banesclass AlertController {
6219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private final Context mContext;
6319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private final AppCompatDialog mDialog;
6419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private final Window mWindow;
6519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
6619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private CharSequence mTitle;
6719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private CharSequence mMessage;
6819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private ListView mListView;
6919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private View mView;
7019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
7119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mViewLayoutResId;
7219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
7319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mViewSpacingLeft;
7419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mViewSpacingTop;
7519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mViewSpacingRight;
7619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mViewSpacingBottom;
7719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private boolean mViewSpacingSpecified = false;
7819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
7919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private Button mButtonPositive;
8019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private CharSequence mButtonPositiveText;
8119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private Message mButtonPositiveMessage;
8219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
8319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private Button mButtonNegative;
8419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private CharSequence mButtonNegativeText;
8519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private Message mButtonNegativeMessage;
8619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
8719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private Button mButtonNeutral;
8819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private CharSequence mButtonNeutralText;
8919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private Message mButtonNeutralMessage;
9019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
91cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    private NestedScrollView mScrollView;
9219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
9319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mIconId = 0;
9419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private Drawable mIcon;
9519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
9619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private ImageView mIconView;
9719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private TextView mTitleView;
9819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private TextView mMessageView;
9919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private View mCustomTitleView;
10019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
10119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private ListAdapter mAdapter;
10219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
10319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mCheckedItem = -1;
10419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
10519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mAlertDialogLayout;
10619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mButtonPanelSideLayout;
10719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mListLayout;
10819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mMultiChoiceItemLayout;
10919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mSingleChoiceItemLayout;
11019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mListItemLayout;
11119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
11219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int mButtonPanelLayoutHint = AlertDialog.LAYOUT_HINT_NONE;
11319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
11419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private Handler mHandler;
11519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
11619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private final View.OnClickListener mButtonHandler = new View.OnClickListener() {
11719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        @Override
11819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public void onClick(View v) {
11919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            final Message m;
12019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (v == mButtonPositive && mButtonPositiveMessage != null) {
12119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                m = Message.obtain(mButtonPositiveMessage);
12219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else if (v == mButtonNegative && mButtonNegativeMessage != null) {
12319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                m = Message.obtain(mButtonNegativeMessage);
12419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else if (v == mButtonNeutral && mButtonNeutralMessage != null) {
12519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                m = Message.obtain(mButtonNeutralMessage);
12619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else {
12719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                m = null;
12819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
12919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
13019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (m != null) {
13119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                m.sendToTarget();
13219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
13319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
13419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            // Post a message so we dismiss after the above handlers are executed
13519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mHandler.obtainMessage(ButtonHandler.MSG_DISMISS_DIALOG, mDialog)
13619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    .sendToTarget();
13719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
13819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    };
13919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
14019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private static final class ButtonHandler extends Handler {
14119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        // Button clicks have Message.what as the BUTTON{1,2,3} constant
14219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        private static final int MSG_DISMISS_DIALOG = 1;
14319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
14419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        private WeakReference<DialogInterface> mDialog;
14519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
14619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public ButtonHandler(DialogInterface dialog) {
14719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mDialog = new WeakReference<>(dialog);
14819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
14919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
15019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        @Override
15119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public void handleMessage(Message msg) {
15219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            switch (msg.what) {
15319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
15419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                case DialogInterface.BUTTON_POSITIVE:
15519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                case DialogInterface.BUTTON_NEGATIVE:
15619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                case DialogInterface.BUTTON_NEUTRAL:
15719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    ((DialogInterface.OnClickListener) msg.obj).onClick(mDialog.get(), msg.what);
15819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    break;
15919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
16019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                case MSG_DISMISS_DIALOG:
16119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    ((DialogInterface) msg.obj).dismiss();
16219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
16319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
16419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
16519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
16619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public AlertController(Context context, AppCompatDialog di, Window window) {
16719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mContext = context;
16819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mDialog = di;
16919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mWindow = window;
17019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mHandler = new ButtonHandler(di);
17119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
172cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final TypedArray a = context.obtainStyledAttributes(null, R.styleable.AlertDialog,
17319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                R.attr.alertDialogStyle, 0);
17419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
17519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mAlertDialogLayout = a.getResourceId(R.styleable.AlertDialog_android_layout, 0);
17619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mButtonPanelSideLayout = a.getResourceId(R.styleable.AlertDialog_buttonPanelSideLayout, 0);
17719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
17819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mListLayout = a.getResourceId(R.styleable.AlertDialog_listLayout, 0);
17919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mMultiChoiceItemLayout = a.getResourceId(R.styleable.AlertDialog_multiChoiceItemLayout, 0);
18019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mSingleChoiceItemLayout = a
18119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                .getResourceId(R.styleable.AlertDialog_singleChoiceItemLayout, 0);
18219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mListItemLayout = a.getResourceId(R.styleable.AlertDialog_listItemLayout, 0);
18319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
18419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        a.recycle();
18519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
18619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
18719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    static boolean canTextInput(View v) {
18819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (v.onCheckIsTextEditor()) {
18919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return true;
19019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
19119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
19219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (!(v instanceof ViewGroup)) {
19319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return false;
19419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
19519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
19619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        ViewGroup vg = (ViewGroup) v;
19719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        int i = vg.getChildCount();
19819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        while (i > 0) {
19919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            i--;
20019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            v = vg.getChildAt(i);
20119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (canTextInput(v)) {
20219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                return true;
20319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
20419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
20519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
20619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        return false;
20719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
20819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
20919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void installContent() {
21019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        /* We use a custom title so never request a window title */
21119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mDialog.supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
21219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        final int contentView = selectContentView();
21319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mDialog.setContentView(contentView);
21419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        setupView();
21519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
21619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
21719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int selectContentView() {
21819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mButtonPanelSideLayout == 0) {
21919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return mAlertDialogLayout;
22019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
22119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mButtonPanelLayoutHint == AlertDialog.LAYOUT_HINT_SIDE) {
22219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return mButtonPanelSideLayout;
22319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
22419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        return mAlertDialogLayout;
22519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
22619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
22719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setTitle(CharSequence title) {
22819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mTitle = title;
22919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mTitleView != null) {
23019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mTitleView.setText(title);
23119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
23219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
23319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
23419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
23519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @see AlertDialog.Builder#setCustomTitle(View)
23619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
23719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setCustomTitle(View customTitleView) {
23819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mCustomTitleView = customTitleView;
23919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
24019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
24119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setMessage(CharSequence message) {
24219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mMessage = message;
24319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mMessageView != null) {
24419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mMessageView.setText(message);
24519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
24619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
24719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
24819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
24919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Set the view resource to display in the dialog.
25019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
25119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setView(int layoutResId) {
25219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mView = null;
25319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewLayoutResId = layoutResId;
25419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingSpecified = false;
25519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
25619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
25719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
25819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Set the view to display in the dialog.
25919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
26019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setView(View view) {
26119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mView = view;
26219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewLayoutResId = 0;
26319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingSpecified = false;
26419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
26519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
26619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
26719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Set the view to display in the dialog along with the spacing around that view
26819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
26919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight,
27019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            int viewSpacingBottom) {
27119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mView = view;
27219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewLayoutResId = 0;
27319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingSpecified = true;
27419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingLeft = viewSpacingLeft;
27519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingTop = viewSpacingTop;
27619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingRight = viewSpacingRight;
27719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingBottom = viewSpacingBottom;
27819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
27919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
28019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
28119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Sets a hint for the best button panel layout.
28219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
28319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setButtonPanelLayoutHint(int layoutHint) {
28419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mButtonPanelLayoutHint = layoutHint;
28519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
28619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
28719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
28819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Sets a click listener or a message to be sent when the button is clicked.
28919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * You only need to pass one of {@code listener} or {@code msg}.
29019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *
29119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param whichButton Which button, can be one of
29219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *                    {@link DialogInterface#BUTTON_POSITIVE},
29319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *                    {@link DialogInterface#BUTTON_NEGATIVE}, or
29419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *                    {@link DialogInterface#BUTTON_NEUTRAL}
29519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param text        The text to display in positive button.
29619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param listener    The {@link DialogInterface.OnClickListener} to use.
29719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param msg         The {@link Message} to be sent when clicked.
29819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
29919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setButton(int whichButton, CharSequence text,
30019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            DialogInterface.OnClickListener listener, Message msg) {
30119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
30219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (msg == null && listener != null) {
30319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            msg = mHandler.obtainMessage(whichButton, listener);
30419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
30519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
30619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        switch (whichButton) {
30719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
30819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            case DialogInterface.BUTTON_POSITIVE:
30919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mButtonPositiveText = text;
31019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mButtonPositiveMessage = msg;
31119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                break;
31219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
31319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            case DialogInterface.BUTTON_NEGATIVE:
31419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mButtonNegativeText = text;
31519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mButtonNegativeMessage = msg;
31619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                break;
31719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
31819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            case DialogInterface.BUTTON_NEUTRAL:
31919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mButtonNeutralText = text;
32019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mButtonNeutralMessage = msg;
32119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                break;
32219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
32319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            default:
32419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                throw new IllegalArgumentException("Button does not exist");
32519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
32619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
32719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
32819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
32919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Specifies the icon to display next to the alert title.
33019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *
33119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param resId the resource identifier of the drawable to use as the icon,
33219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *              or 0 for no icon
33319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
33419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setIcon(int resId) {
33519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mIcon = null;
33619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mIconId = resId;
33719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
33819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mIconView != null) {
33919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (resId != 0) {
340acaff9dcb3cefc4f47ba16ca1168d8537b3a24e6Chris Banes                mIconView.setVisibility(View.VISIBLE);
34119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mIconView.setImageResource(mIconId);
34219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else {
34319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mIconView.setVisibility(View.GONE);
34419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
34519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
34619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
34719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
34819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
34919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Specifies the icon to display next to the alert title.
35019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *
35119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param icon the drawable to use as the icon or null for no icon
35219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
35319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setIcon(Drawable icon) {
35419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mIcon = icon;
35519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mIconId = 0;
35619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
35719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mIconView != null) {
35819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (icon != null) {
35958c14e5c83aa8f836aff6e48ad90e6976948f1acChris Banes                mIconView.setVisibility(View.VISIBLE);
36019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mIconView.setImageDrawable(icon);
36119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else {
36219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mIconView.setVisibility(View.GONE);
36319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
36419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
36519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
36619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
36719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
36819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param attrId the attributeId of the theme-specific drawable
36919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *               to resolve the resourceId for.
370cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     *
37119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @return resId the resourceId of the theme-specific drawable
37219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
37319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public int getIconAttributeResId(int attrId) {
37419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        TypedValue out = new TypedValue();
37519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mContext.getTheme().resolveAttribute(attrId, out, true);
37619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        return out.resourceId;
37719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
37819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
37919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public ListView getListView() {
38019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        return mListView;
38119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
38219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
38319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public Button getButton(int whichButton) {
38419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        switch (whichButton) {
38519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            case DialogInterface.BUTTON_POSITIVE:
38619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                return mButtonPositive;
38719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            case DialogInterface.BUTTON_NEGATIVE:
38819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                return mButtonNegative;
38919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            case DialogInterface.BUTTON_NEUTRAL:
39019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                return mButtonNeutral;
39119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            default:
39219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                return null;
39319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
39419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
39519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
39619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    @SuppressWarnings({"UnusedDeclaration"})
39719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public boolean onKeyDown(int keyCode, KeyEvent event) {
39819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        return mScrollView != null && mScrollView.executeKeyEvent(event);
39919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
40019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
40119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    @SuppressWarnings({"UnusedDeclaration"})
40219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public boolean onKeyUp(int keyCode, KeyEvent event) {
40319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        return mScrollView != null && mScrollView.executeKeyEvent(event);
40419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
40519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
406cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    /**
407cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     * Resolves whether a custom or default panel should be used. Removes the
408cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     * default panel if a custom panel should be used. If the resolved panel is
409cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     * a view stub, inflates before returning.
410cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     *
411cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     * @param customPanel the custom panel
412cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     * @param defaultPanel the default panel
413cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     * @return the panel to use
414cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     */
415cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    @Nullable
416cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    private ViewGroup resolvePanel(@Nullable View customPanel, @Nullable View defaultPanel) {
417cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (customPanel == null) {
418cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            // Inflate the default panel, if needed.
419cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (defaultPanel instanceof ViewStub) {
420cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                defaultPanel = ((ViewStub) defaultPanel).inflate();
421cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
422cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
423cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            return (ViewGroup) defaultPanel;
424cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
425cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
426cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Remove the default panel entirely.
427cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (defaultPanel != null) {
428cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            final ViewParent parent = defaultPanel.getParent();
429cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (parent instanceof ViewGroup) {
430cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                ((ViewGroup) parent).removeView(defaultPanel);
431cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
432cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
433cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
434cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Inflate the custom panel, if needed.
435cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (customPanel instanceof ViewStub) {
436cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            customPanel = ((ViewStub) customPanel).inflate();
437cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
438cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
439cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        return (ViewGroup) customPanel;
440cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    }
441cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
44219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private void setupView() {
443cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View parentPanel = mWindow.findViewById(R.id.parentPanel);
444cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View defaultTopPanel = parentPanel.findViewById(R.id.topPanel);
445cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View defaultContentPanel = parentPanel.findViewById(R.id.contentPanel);
446cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View defaultButtonPanel = parentPanel.findViewById(R.id.buttonPanel);
447cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
448cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Install custom content before setting up the title or buttons so
449cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // that we can handle panel overrides.
450cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final ViewGroup customPanel = (ViewGroup) parentPanel.findViewById(R.id.customPanel);
451cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        setupCustomContent(customPanel);
452cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
453cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View customTopPanel = customPanel.findViewById(R.id.topPanel);
454cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View customContentPanel = customPanel.findViewById(R.id.contentPanel);
455cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View customButtonPanel = customPanel.findViewById(R.id.buttonPanel);
456cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
457cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Resolve the correct panels and remove the defaults, if needed.
458cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final ViewGroup topPanel = resolvePanel(customTopPanel, defaultTopPanel);
459cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final ViewGroup contentPanel = resolvePanel(customContentPanel, defaultContentPanel);
460cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final ViewGroup buttonPanel = resolvePanel(customButtonPanel, defaultButtonPanel);
461cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
46219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        setupContent(contentPanel);
463cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        setupButtons(buttonPanel);
464cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        setupTitle(topPanel);
465cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
466cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final boolean hasCustomPanel = customPanel != null
467cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                && customPanel.getVisibility() != View.GONE;
468cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final boolean hasTopPanel = topPanel != null
469cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                && topPanel.getVisibility() != View.GONE;
470cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final boolean hasButtonPanel = buttonPanel != null
471cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                && buttonPanel.getVisibility() != View.GONE;
472cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
473cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Only display the text spacer if we don't have buttons.
474cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (!hasButtonPanel) {
475cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (contentPanel != null) {
476cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                final View spacer = contentPanel.findViewById(R.id.textSpacerNoButtons);
477cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                if (spacer != null) {
478cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    spacer.setVisibility(View.VISIBLE);
479cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                }
480cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
481cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
48219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
483cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (hasTopPanel) {
484cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            // Only clip scrolling content to padding if we have a title.
485cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (mScrollView != null) {
486cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                mScrollView.setClipToPadding(true);
487cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
488cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
48919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
490cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Update scroll indicators as needed.
491cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (!hasCustomPanel) {
492cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            final View content = mListView != null ? mListView : mScrollView;
493cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (content != null) {
494cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                final int indicators = (hasTopPanel ? ViewCompat.SCROLL_INDICATOR_TOP : 0)
495cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        | (hasButtonPanel ? ViewCompat.SCROLL_INDICATOR_BOTTOM : 0);
496cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                setScrollIndicators(contentPanel, content, indicators,
497cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        ViewCompat.SCROLL_INDICATOR_TOP | ViewCompat.SCROLL_INDICATOR_BOTTOM);
498cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
499cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
500cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
501cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final ListView listView = mListView;
502cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (listView != null && mAdapter != null) {
503cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            listView.setAdapter(mAdapter);
504cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            final int checkedItem = mCheckedItem;
505cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (checkedItem > -1) {
506cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                listView.setItemChecked(checkedItem, true);
507cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                listView.setSelection(checkedItem);
508cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
509cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
510cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    }
511cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
512cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    private void setScrollIndicators(ViewGroup contentPanel, View content,
513cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            final int indicators, final int mask) {
514cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Set up scroll indicators (if present).
515cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        View indicatorUp = mWindow.findViewById(R.id.scrollIndicatorUp);
516cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        View indicatorDown = mWindow.findViewById(R.id.scrollIndicatorDown);
517cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
518cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (Build.VERSION.SDK_INT >= 23) {
519cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            // We're on Marshmallow so can rely on the View APIs
520cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            ViewCompat.setScrollIndicators(content, indicators, mask);
521cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            // We can also remove the compat indicator views
522cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (indicatorUp != null) {
523cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                contentPanel.removeView(indicatorUp);
524cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
525cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (indicatorDown != null) {
526cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                contentPanel.removeView(indicatorDown);
527cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
528cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        } else {
529cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            // First, remove the indicator views if we're not set to use them
530cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (indicatorUp != null && (indicators & ViewCompat.SCROLL_INDICATOR_TOP) == 0) {
531cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                contentPanel.removeView(indicatorUp);
532cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                indicatorUp = null;
533cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
534cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (indicatorDown != null && (indicators & ViewCompat.SCROLL_INDICATOR_BOTTOM) == 0) {
535cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                contentPanel.removeView(indicatorDown);
536cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                indicatorDown = null;
537cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
538cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
539cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (indicatorUp != null || indicatorDown != null) {
540cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                final View top = indicatorUp;
541cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                final View bottom = indicatorDown;
542cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
543cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                if (mMessage != null) {
544cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    // We're just showing the ScrollView, set up listener.
545cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    mScrollView.setOnScrollChangeListener(
546cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            new NestedScrollView.OnScrollChangeListener() {
547cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                @Override
548cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                public void onScrollChange(NestedScrollView v, int scrollX,
549cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                        int scrollY,
550cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                        int oldScrollX, int oldScrollY) {
551cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                    manageScrollIndicators(v, top, bottom);
552cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                }
553cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            });
554cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    // Set up the indicators following layout.
555cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    mScrollView.post(new Runnable() {
556cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        @Override
557cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        public void run() {
558cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            manageScrollIndicators(mScrollView, top, bottom);
559cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        }
560cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    });
561cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                } else if (mListView != null) {
562cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    // We're just showing the AbsListView, set up listener.
563cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
564cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        @Override
565cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        public void onScrollStateChanged(AbsListView view, int scrollState) {}
566cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
567cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        @Override
568cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        public void onScroll(AbsListView v, int firstVisibleItem,
569cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                int visibleItemCount, int totalItemCount) {
570cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            manageScrollIndicators(v, top, bottom);
571cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        }
572cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    });
573cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    // Set up the indicators following layout.
574cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    mListView.post(new Runnable() {
575cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        @Override
576cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        public void run() {
577cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            manageScrollIndicators(mListView, top, bottom);
578cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        }
579cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    });
580cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                } else {
581cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    // We don't have any content to scroll, remove the indicators.
582cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    if (top != null) {
583cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        contentPanel.removeView(top);
584cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    }
585cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    if (bottom != null) {
586cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        contentPanel.removeView(bottom);
587cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    }
588cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                }
58919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
59019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
591cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    }
59219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
593cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    private void setupCustomContent(ViewGroup customPanel) {
59419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        final View customView;
59519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mView != null) {
59619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            customView = mView;
59719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else if (mViewLayoutResId != 0) {
59819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            final LayoutInflater inflater = LayoutInflater.from(mContext);
59919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            customView = inflater.inflate(mViewLayoutResId, customPanel, false);
60019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
60119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            customView = null;
60219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
60319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
60419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        final boolean hasCustomView = customView != null;
60519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (!hasCustomView || !canTextInput(customView)) {
60619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mWindow.setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
60719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
60819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
60919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
61019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (hasCustomView) {
61119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            final FrameLayout custom = (FrameLayout) mWindow.findViewById(R.id.custom);
61219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            custom.addView(customView, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
61319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
61419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mViewSpacingSpecified) {
61519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                custom.setPadding(
61619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight, mViewSpacingBottom);
61719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
61819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
61919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mListView != null) {
62019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                ((LinearLayout.LayoutParams) customPanel.getLayoutParams()).weight = 0;
62119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
62219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
62319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            customPanel.setVisibility(View.GONE);
62419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
62519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
62619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
627cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    private void setupTitle(ViewGroup topPanel) {
62819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mCustomTitleView != null) {
62919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            // Add the custom title view directly to the topPanel layout
63019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            LayoutParams lp = new LayoutParams(
63119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
63219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
63319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            topPanel.addView(mCustomTitleView, 0, lp);
63419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
63519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            // Hide the title template
63619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            View titleTemplate = mWindow.findViewById(R.id.title_template);
63719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            titleTemplate.setVisibility(View.GONE);
63819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
63919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mIconView = (ImageView) mWindow.findViewById(android.R.id.icon);
64019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
64119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            final boolean hasTextTitle = !TextUtils.isEmpty(mTitle);
64219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (hasTextTitle) {
64319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                // Display the title if a title is supplied, else hide it.
64419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mTitleView = (TextView) mWindow.findViewById(R.id.alertTitle);
64519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mTitleView.setText(mTitle);
64619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
64719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                // Do this last so that if the user has supplied any icons we
64819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                // use them instead of the default ones. If the user has
64919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                // specified 0 then make it disappear.
65019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mIconId != 0) {
65119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    mIconView.setImageResource(mIconId);
65219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                } else if (mIcon != null) {
65319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    mIconView.setImageDrawable(mIcon);
65419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                } else {
65519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    // Apply the padding from the icon to ensure the title is
65619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    // aligned correctly.
65719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    mTitleView.setPadding(mIconView.getPaddingLeft(),
65819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mIconView.getPaddingTop(),
65919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mIconView.getPaddingRight(),
66019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mIconView.getPaddingBottom());
66119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    mIconView.setVisibility(View.GONE);
66219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
66319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else {
66419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                // Hide the title template
66519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                final View titleTemplate = mWindow.findViewById(R.id.title_template);
66619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                titleTemplate.setVisibility(View.GONE);
66719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mIconView.setVisibility(View.GONE);
66819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                topPanel.setVisibility(View.GONE);
66919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
67019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
67119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
67219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
67319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private void setupContent(ViewGroup contentPanel) {
674cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        mScrollView = (NestedScrollView) mWindow.findViewById(R.id.scrollView);
67519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mScrollView.setFocusable(false);
676cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        mScrollView.setNestedScrollingEnabled(false);
67719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
67819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        // Special case for users that only want to display a String
679cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        mMessageView = (TextView) contentPanel.findViewById(android.R.id.message);
68019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mMessageView == null) {
68119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return;
68219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
68319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
68419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mMessage != null) {
68519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mMessageView.setText(mMessage);
68619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
68719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mMessageView.setVisibility(View.GONE);
68819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mScrollView.removeView(mMessageView);
68919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
69019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mListView != null) {
69119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                final ViewGroup scrollParent = (ViewGroup) mScrollView.getParent();
69219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                final int childIndex = scrollParent.indexOfChild(mScrollView);
69319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                scrollParent.removeViewAt(childIndex);
69419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                scrollParent.addView(mListView, childIndex,
69519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        new LayoutParams(MATCH_PARENT, MATCH_PARENT));
69619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else {
69719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                contentPanel.setVisibility(View.GONE);
69819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
69919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
70019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
70119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
702cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    private static void manageScrollIndicators(View v, View upIndicator, View downIndicator) {
703cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (upIndicator != null) {
704cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            upIndicator.setVisibility(
705cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    ViewCompat.canScrollVertically(v, -1) ? View.VISIBLE : View.INVISIBLE);
706cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
707cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (downIndicator != null) {
708cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            downIndicator.setVisibility(
709cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    ViewCompat.canScrollVertically(v, 1) ? View.VISIBLE : View.INVISIBLE);
710cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
711cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    }
712cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
713cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    private void setupButtons(ViewGroup buttonPanel) {
71419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        int BIT_BUTTON_POSITIVE = 1;
71519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        int BIT_BUTTON_NEGATIVE = 2;
71619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        int BIT_BUTTON_NEUTRAL = 4;
71719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        int whichButtons = 0;
718cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        mButtonPositive = (Button) buttonPanel.findViewById(android.R.id.button1);
71919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mButtonPositive.setOnClickListener(mButtonHandler);
72019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
72119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (TextUtils.isEmpty(mButtonPositiveText)) {
72219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonPositive.setVisibility(View.GONE);
72319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
72419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonPositive.setText(mButtonPositiveText);
72519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonPositive.setVisibility(View.VISIBLE);
72619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            whichButtons = whichButtons | BIT_BUTTON_POSITIVE;
72719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
72819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
729cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        mButtonNegative = (Button) buttonPanel.findViewById(android.R.id.button2);
73019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mButtonNegative.setOnClickListener(mButtonHandler);
73119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
73219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (TextUtils.isEmpty(mButtonNegativeText)) {
73319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonNegative.setVisibility(View.GONE);
73419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
73519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonNegative.setText(mButtonNegativeText);
73619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonNegative.setVisibility(View.VISIBLE);
73719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
73819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            whichButtons = whichButtons | BIT_BUTTON_NEGATIVE;
73919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
74019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
741cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        mButtonNeutral = (Button) buttonPanel.findViewById(android.R.id.button3);
74219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mButtonNeutral.setOnClickListener(mButtonHandler);
74319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
74419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (TextUtils.isEmpty(mButtonNeutralText)) {
74519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonNeutral.setVisibility(View.GONE);
74619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
74719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonNeutral.setText(mButtonNeutralText);
74819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonNeutral.setVisibility(View.VISIBLE);
74919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
75019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            whichButtons = whichButtons | BIT_BUTTON_NEUTRAL;
75119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
75219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
753cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final boolean hasButtons = whichButtons != 0;
754cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (!hasButtons) {
755cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            buttonPanel.setVisibility(View.GONE);
75619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
75719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
75819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
75919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public static class AlertParams {
76019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public final Context mContext;
76119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public final LayoutInflater mInflater;
76219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
76319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mIconId = 0;
76419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public Drawable mIcon;
76519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mIconAttrId = 0;
76619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CharSequence mTitle;
76719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public View mCustomTitleView;
76819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CharSequence mMessage;
76919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CharSequence mPositiveButtonText;
77019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnClickListener mPositiveButtonListener;
77119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CharSequence mNegativeButtonText;
77219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnClickListener mNegativeButtonListener;
77319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CharSequence mNeutralButtonText;
77419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnClickListener mNeutralButtonListener;
77519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean mCancelable;
77619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnCancelListener mOnCancelListener;
77719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnDismissListener mOnDismissListener;
77819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnKeyListener mOnKeyListener;
77919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CharSequence[] mItems;
78019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public ListAdapter mAdapter;
78119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnClickListener mOnClickListener;
78219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mViewLayoutResId;
78319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public View mView;
78419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mViewSpacingLeft;
78519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mViewSpacingTop;
78619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mViewSpacingRight;
78719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mViewSpacingBottom;
78819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean mViewSpacingSpecified = false;
78919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean[] mCheckedItems;
79019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean mIsMultiChoice;
79119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean mIsSingleChoice;
79219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mCheckedItem = -1;
79319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnMultiChoiceClickListener mOnCheckboxClickListener;
79419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public Cursor mCursor;
79519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public String mLabelColumn;
79619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public String mIsCheckedColumn;
79719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean mForceInverseBackground;
79819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public AdapterView.OnItemSelectedListener mOnItemSelectedListener;
79919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public OnPrepareListViewListener mOnPrepareListViewListener;
80019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean mRecycleOnMeasure = true;
80119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
80219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        /**
80319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes         * Interface definition for a callback to be invoked before the ListView
80419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes         * will be bound to an adapter.
80519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes         */
80619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public interface OnPrepareListViewListener {
80719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
80819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            /**
80919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes             * Called before the ListView is bound to an adapter.
81019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes             * @param listView The ListView that will be shown in the dialog.
81119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes             */
81219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            void onPrepareListView(ListView listView);
81319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
81419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
81519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public AlertParams(Context context) {
81619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mContext = context;
81719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mCancelable = true;
81819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
81919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
82019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
82119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public void apply(AlertController dialog) {
82219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mCustomTitleView != null) {
82319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setCustomTitle(mCustomTitleView);
82419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else {
82519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mTitle != null) {
82619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    dialog.setTitle(mTitle);
82719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
82819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mIcon != null) {
82919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    dialog.setIcon(mIcon);
83019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
83119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mIconId != 0) {
83219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    dialog.setIcon(mIconId);
83319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
83419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mIconAttrId != 0) {
83519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    dialog.setIcon(dialog.getIconAttributeResId(mIconAttrId));
83619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
83719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
83819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mMessage != null) {
83919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setMessage(mMessage);
84019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
84119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mPositiveButtonText != null) {
84219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setButton(DialogInterface.BUTTON_POSITIVE, mPositiveButtonText,
84319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        mPositiveButtonListener, null);
84419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
84519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mNegativeButtonText != null) {
84619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setButton(DialogInterface.BUTTON_NEGATIVE, mNegativeButtonText,
84719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        mNegativeButtonListener, null);
84819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
84919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mNeutralButtonText != null) {
85019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setButton(DialogInterface.BUTTON_NEUTRAL, mNeutralButtonText,
85119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        mNeutralButtonListener, null);
85219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
85319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            // For a list, the client can either supply an array of items or an
85419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            // adapter or a cursor
85519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if ((mItems != null) || (mCursor != null) || (mAdapter != null)) {
85619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                createListView(dialog);
85719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
85819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mView != null) {
85919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mViewSpacingSpecified) {
86019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    dialog.setView(mView, mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight,
86119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mViewSpacingBottom);
86219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                } else {
86319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    dialog.setView(mView);
86419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
86519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else if (mViewLayoutResId != 0) {
86619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setView(mViewLayoutResId);
86719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
86819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
86919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            /*
87019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            dialog.setCancelable(mCancelable);
87119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            dialog.setOnCancelListener(mOnCancelListener);
87219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mOnKeyListener != null) {
87319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setOnKeyListener(mOnKeyListener);
87419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
87519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            */
87619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
87719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
87819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        private void createListView(final AlertController dialog) {
87919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            final ListView listView = (ListView) mInflater.inflate(dialog.mListLayout, null);
880cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            final ListAdapter adapter;
88119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
88219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mIsMultiChoice) {
88319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mCursor == null) {
88419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    adapter = new ArrayAdapter<CharSequence>(
88519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mContext, dialog.mMultiChoiceItemLayout, android.R.id.text1, mItems) {
88619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        @Override
88719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        public View getView(int position, View convertView, ViewGroup parent) {
88819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            View view = super.getView(position, convertView, parent);
88919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            if (mCheckedItems != null) {
89019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                boolean isItemChecked = mCheckedItems[position];
89119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                if (isItemChecked) {
89219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                    listView.setItemChecked(position, true);
89319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                }
89419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            }
89519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            return view;
89619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        }
89719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    };
89819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                } else {
89919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    adapter = new CursorAdapter(mContext, mCursor, false) {
90019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        private final int mLabelIndex;
90119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        private final int mIsCheckedIndex;
90219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
90319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        {
90419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            final Cursor cursor = getCursor();
90519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mLabelIndex = cursor.getColumnIndexOrThrow(mLabelColumn);
90619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mIsCheckedIndex = cursor.getColumnIndexOrThrow(mIsCheckedColumn);
90719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        }
90819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
90919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        @Override
91019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        public void bindView(View view, Context context, Cursor cursor) {
911cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            CheckedTextView text = (CheckedTextView) view.findViewById(
912cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                    android.R.id.text1);
91319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            text.setText(cursor.getString(mLabelIndex));
91419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            listView.setItemChecked(cursor.getPosition(),
91519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                    cursor.getInt(mIsCheckedIndex) == 1);
91619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        }
91719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
91819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        @Override
91919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        public View newView(Context context, Cursor cursor, ViewGroup parent) {
92019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            return mInflater.inflate(dialog.mMultiChoiceItemLayout,
92119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                    parent, false);
92219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        }
92319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
92419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    };
92519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
92619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else {
927cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                final int layout;
928cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                if (mIsSingleChoice) {
929cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    layout = dialog.mSingleChoiceItemLayout;
930cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                } else {
931cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    layout = dialog.mListItemLayout;
932cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                }
933cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
934cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                if (mCursor != null) {
935cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    adapter = new SimpleCursorAdapter(mContext, layout, mCursor,
936cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            new String[] { mLabelColumn }, new int[] { android.R.id.text1 });
937cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                } else if (mAdapter != null) {
938cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    adapter = mAdapter;
93919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                } else {
940cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    adapter = new CheckedItemAdapter(mContext, layout, android.R.id.text1, mItems);
94119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
94219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
94319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
94419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mOnPrepareListViewListener != null) {
94519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mOnPrepareListViewListener.onPrepareListView(listView);
94619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
94719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
94819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            /* Don't directly set the adapter on the ListView as we might
94919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes             * want to add a footer to the ListView later.
95019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes             */
95119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            dialog.mAdapter = adapter;
95219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            dialog.mCheckedItem = mCheckedItem;
95319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
95419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mOnClickListener != null) {
95519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                listView.setOnItemClickListener(new OnItemClickListener() {
95619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    @Override
95719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
95819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        mOnClickListener.onClick(dialog.mDialog, position);
95919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        if (!mIsSingleChoice) {
96019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            dialog.mDialog.dismiss();
96119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        }
96219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    }
96319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                });
96419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else if (mOnCheckboxClickListener != null) {
96519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                listView.setOnItemClickListener(new OnItemClickListener() {
96619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    @Override
96719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
96819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        if (mCheckedItems != null) {
96919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mCheckedItems[position] = listView.isItemChecked(position);
97019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        }
97119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        mOnCheckboxClickListener.onClick(
97219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                dialog.mDialog, position, listView.isItemChecked(position));
97319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    }
97419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                });
97519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
97619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
97719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            // Attach a given OnItemSelectedListener to the ListView
97819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mOnItemSelectedListener != null) {
97919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                listView.setOnItemSelectedListener(mOnItemSelectedListener);
98019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
98119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
98219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mIsSingleChoice) {
98319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
98419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else if (mIsMultiChoice) {
98519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
98619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
98719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            dialog.mListView = listView;
98819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
98919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
99019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
99119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private static class CheckedItemAdapter extends ArrayAdapter<CharSequence> {
99219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CheckedItemAdapter(Context context, int resource, int textViewResourceId,
99319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                CharSequence[] objects) {
99419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            super(context, resource, textViewResourceId, objects);
99519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
99619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
99719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        @Override
99819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean hasStableIds() {
99919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return true;
100019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
100119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
100219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        @Override
100319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public long getItemId(int position) {
100419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return position;
100519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
100619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
100719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes}
1008