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();
1852e4451763a8a4778d9703b106fbe90d9fd5c7342Chris Banes
1862e4451763a8a4778d9703b106fbe90d9fd5c7342Chris Banes        /* We use a custom title so never request a window title */
1872e4451763a8a4778d9703b106fbe90d9fd5c7342Chris Banes        di.supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
18819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
18919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
19019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    static boolean canTextInput(View v) {
19119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (v.onCheckIsTextEditor()) {
19219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return true;
19319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
19419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
19519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (!(v instanceof ViewGroup)) {
19619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return false;
19719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
19819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
19919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        ViewGroup vg = (ViewGroup) v;
20019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        int i = vg.getChildCount();
20119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        while (i > 0) {
20219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            i--;
20319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            v = vg.getChildAt(i);
20419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (canTextInput(v)) {
20519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                return true;
20619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
20719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
20819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
20919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        return false;
21019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
21119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
21219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void installContent() {
21319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        final int contentView = selectContentView();
21419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mDialog.setContentView(contentView);
21519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        setupView();
21619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
21719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
21819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private int selectContentView() {
21919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mButtonPanelSideLayout == 0) {
22019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return mAlertDialogLayout;
22119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
22219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mButtonPanelLayoutHint == AlertDialog.LAYOUT_HINT_SIDE) {
22319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return mButtonPanelSideLayout;
22419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
22519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        return mAlertDialogLayout;
22619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
22719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
22819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setTitle(CharSequence title) {
22919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mTitle = title;
23019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mTitleView != null) {
23119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mTitleView.setText(title);
23219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
23319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
23419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
23519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
23619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @see AlertDialog.Builder#setCustomTitle(View)
23719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
23819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setCustomTitle(View customTitleView) {
23919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mCustomTitleView = customTitleView;
24019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
24119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
24219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setMessage(CharSequence message) {
24319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mMessage = message;
24419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mMessageView != null) {
24519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mMessageView.setText(message);
24619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
24719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
24819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
24919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
25019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Set the view resource to display in the dialog.
25119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
25219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setView(int layoutResId) {
25319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mView = null;
25419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewLayoutResId = layoutResId;
25519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingSpecified = false;
25619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
25719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
25819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
25919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Set the view to display in the dialog.
26019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
26119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setView(View view) {
26219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mView = view;
26319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewLayoutResId = 0;
26419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingSpecified = false;
26519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
26619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
26719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
26819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Set the view to display in the dialog along with the spacing around that view
26919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
27019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight,
27119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            int viewSpacingBottom) {
27219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mView = view;
27319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewLayoutResId = 0;
27419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingSpecified = true;
27519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingLeft = viewSpacingLeft;
27619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingTop = viewSpacingTop;
27719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingRight = viewSpacingRight;
27819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mViewSpacingBottom = viewSpacingBottom;
27919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
28019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
28119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
28219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Sets a hint for the best button panel layout.
28319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
28419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setButtonPanelLayoutHint(int layoutHint) {
28519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mButtonPanelLayoutHint = layoutHint;
28619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
28719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
28819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
28919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Sets a click listener or a message to be sent when the button is clicked.
29019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * You only need to pass one of {@code listener} or {@code msg}.
29119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *
29219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param whichButton Which button, can be one of
29319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *                    {@link DialogInterface#BUTTON_POSITIVE},
29419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *                    {@link DialogInterface#BUTTON_NEGATIVE}, or
29519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *                    {@link DialogInterface#BUTTON_NEUTRAL}
29619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param text        The text to display in positive button.
29719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param listener    The {@link DialogInterface.OnClickListener} to use.
29819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param msg         The {@link Message} to be sent when clicked.
29919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
30019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setButton(int whichButton, CharSequence text,
30119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            DialogInterface.OnClickListener listener, Message msg) {
30219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
30319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (msg == null && listener != null) {
30419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            msg = mHandler.obtainMessage(whichButton, listener);
30519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
30619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
30719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        switch (whichButton) {
30819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
30919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            case DialogInterface.BUTTON_POSITIVE:
31019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mButtonPositiveText = text;
31119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mButtonPositiveMessage = msg;
31219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                break;
31319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
31419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            case DialogInterface.BUTTON_NEGATIVE:
31519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mButtonNegativeText = text;
31619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mButtonNegativeMessage = msg;
31719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                break;
31819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
31919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            case DialogInterface.BUTTON_NEUTRAL:
32019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mButtonNeutralText = text;
32119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mButtonNeutralMessage = msg;
32219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                break;
32319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
32419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            default:
32519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                throw new IllegalArgumentException("Button does not exist");
32619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
32719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
32819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
32919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
33019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Specifies the icon to display next to the alert title.
33119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *
33219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param resId the resource identifier of the drawable to use as the icon,
33319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *              or 0 for no icon
33419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
33519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setIcon(int resId) {
33619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mIcon = null;
33719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mIconId = resId;
33819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
33919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mIconView != null) {
34019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (resId != 0) {
341acaff9dcb3cefc4f47ba16ca1168d8537b3a24e6Chris Banes                mIconView.setVisibility(View.VISIBLE);
34219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mIconView.setImageResource(mIconId);
34319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else {
34419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mIconView.setVisibility(View.GONE);
34519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
34619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
34719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
34819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
34919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
35019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * Specifies the icon to display next to the alert title.
35119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *
35219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param icon the drawable to use as the icon or null for no icon
35319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
35419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public void setIcon(Drawable icon) {
35519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mIcon = icon;
35619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mIconId = 0;
35719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
35819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mIconView != null) {
35919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (icon != null) {
36058c14e5c83aa8f836aff6e48ad90e6976948f1acChris Banes                mIconView.setVisibility(View.VISIBLE);
36119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mIconView.setImageDrawable(icon);
36219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else {
36319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mIconView.setVisibility(View.GONE);
36419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
36519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
36619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
36719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
36819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    /**
36919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @param attrId the attributeId of the theme-specific drawable
37019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     *               to resolve the resourceId for.
371cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     *
37219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     * @return resId the resourceId of the theme-specific drawable
37319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes     */
37419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public int getIconAttributeResId(int attrId) {
37519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        TypedValue out = new TypedValue();
37619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mContext.getTheme().resolveAttribute(attrId, out, true);
37719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        return out.resourceId;
37819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
37919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
38019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public ListView getListView() {
38119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        return mListView;
38219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
38319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
38419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public Button getButton(int whichButton) {
38519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        switch (whichButton) {
38619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            case DialogInterface.BUTTON_POSITIVE:
38719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                return mButtonPositive;
38819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            case DialogInterface.BUTTON_NEGATIVE:
38919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                return mButtonNegative;
39019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            case DialogInterface.BUTTON_NEUTRAL:
39119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                return mButtonNeutral;
39219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            default:
39319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                return null;
39419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
39519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
39619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
39719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    @SuppressWarnings({"UnusedDeclaration"})
39819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public boolean onKeyDown(int keyCode, KeyEvent event) {
39919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        return mScrollView != null && mScrollView.executeKeyEvent(event);
40019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
40119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
40219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    @SuppressWarnings({"UnusedDeclaration"})
40319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public boolean onKeyUp(int keyCode, KeyEvent event) {
40419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        return mScrollView != null && mScrollView.executeKeyEvent(event);
40519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
40619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
407cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    /**
408cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     * Resolves whether a custom or default panel should be used. Removes the
409cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     * default panel if a custom panel should be used. If the resolved panel is
410cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     * a view stub, inflates before returning.
411cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     *
412cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     * @param customPanel the custom panel
413cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     * @param defaultPanel the default panel
414cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     * @return the panel to use
415cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes     */
416cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    @Nullable
417cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    private ViewGroup resolvePanel(@Nullable View customPanel, @Nullable View defaultPanel) {
418cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (customPanel == null) {
419cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            // Inflate the default panel, if needed.
420cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (defaultPanel instanceof ViewStub) {
421cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                defaultPanel = ((ViewStub) defaultPanel).inflate();
422cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
423cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
424cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            return (ViewGroup) defaultPanel;
425cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
426cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
427cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Remove the default panel entirely.
428cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (defaultPanel != null) {
429cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            final ViewParent parent = defaultPanel.getParent();
430cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (parent instanceof ViewGroup) {
431cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                ((ViewGroup) parent).removeView(defaultPanel);
432cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
433cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
434cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
435cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Inflate the custom panel, if needed.
436cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (customPanel instanceof ViewStub) {
437cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            customPanel = ((ViewStub) customPanel).inflate();
438cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
439cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
440cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        return (ViewGroup) customPanel;
441cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    }
442cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
44319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private void setupView() {
444cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View parentPanel = mWindow.findViewById(R.id.parentPanel);
445cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View defaultTopPanel = parentPanel.findViewById(R.id.topPanel);
446cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View defaultContentPanel = parentPanel.findViewById(R.id.contentPanel);
447cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View defaultButtonPanel = parentPanel.findViewById(R.id.buttonPanel);
448cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
449cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Install custom content before setting up the title or buttons so
450cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // that we can handle panel overrides.
451cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final ViewGroup customPanel = (ViewGroup) parentPanel.findViewById(R.id.customPanel);
452cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        setupCustomContent(customPanel);
453cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
454cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View customTopPanel = customPanel.findViewById(R.id.topPanel);
455cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View customContentPanel = customPanel.findViewById(R.id.contentPanel);
456cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final View customButtonPanel = customPanel.findViewById(R.id.buttonPanel);
457cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
458cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Resolve the correct panels and remove the defaults, if needed.
459cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final ViewGroup topPanel = resolvePanel(customTopPanel, defaultTopPanel);
460cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final ViewGroup contentPanel = resolvePanel(customContentPanel, defaultContentPanel);
461cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final ViewGroup buttonPanel = resolvePanel(customButtonPanel, defaultButtonPanel);
462cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
46319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        setupContent(contentPanel);
464cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        setupButtons(buttonPanel);
465cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        setupTitle(topPanel);
466cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
467cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final boolean hasCustomPanel = customPanel != null
468cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                && customPanel.getVisibility() != View.GONE;
469cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final boolean hasTopPanel = topPanel != null
470cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                && topPanel.getVisibility() != View.GONE;
471cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final boolean hasButtonPanel = buttonPanel != null
472cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                && buttonPanel.getVisibility() != View.GONE;
473cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
474cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Only display the text spacer if we don't have buttons.
475cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (!hasButtonPanel) {
476cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (contentPanel != null) {
477cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                final View spacer = contentPanel.findViewById(R.id.textSpacerNoButtons);
478cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                if (spacer != null) {
479cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    spacer.setVisibility(View.VISIBLE);
480cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                }
481cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
482cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
48319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
484cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (hasTopPanel) {
485cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            // Only clip scrolling content to padding if we have a title.
486cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (mScrollView != null) {
487cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                mScrollView.setClipToPadding(true);
488cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
489cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
49019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
491cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Update scroll indicators as needed.
492cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (!hasCustomPanel) {
493cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            final View content = mListView != null ? mListView : mScrollView;
494cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (content != null) {
495cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                final int indicators = (hasTopPanel ? ViewCompat.SCROLL_INDICATOR_TOP : 0)
496cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        | (hasButtonPanel ? ViewCompat.SCROLL_INDICATOR_BOTTOM : 0);
497cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                setScrollIndicators(contentPanel, content, indicators,
498cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        ViewCompat.SCROLL_INDICATOR_TOP | ViewCompat.SCROLL_INDICATOR_BOTTOM);
499cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
500cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
501cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
502cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final ListView listView = mListView;
503cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (listView != null && mAdapter != null) {
504cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            listView.setAdapter(mAdapter);
505cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            final int checkedItem = mCheckedItem;
506cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (checkedItem > -1) {
507cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                listView.setItemChecked(checkedItem, true);
508cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                listView.setSelection(checkedItem);
509cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
510cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
511cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    }
512cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
513cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    private void setScrollIndicators(ViewGroup contentPanel, View content,
514cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            final int indicators, final int mask) {
515cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        // Set up scroll indicators (if present).
516cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        View indicatorUp = mWindow.findViewById(R.id.scrollIndicatorUp);
517cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        View indicatorDown = mWindow.findViewById(R.id.scrollIndicatorDown);
518cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
519cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (Build.VERSION.SDK_INT >= 23) {
520cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            // We're on Marshmallow so can rely on the View APIs
521cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            ViewCompat.setScrollIndicators(content, indicators, mask);
522cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            // We can also remove the compat indicator views
523cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (indicatorUp != null) {
524cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                contentPanel.removeView(indicatorUp);
525cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
526cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (indicatorDown != null) {
527cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                contentPanel.removeView(indicatorDown);
528cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
529cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        } else {
530cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            // First, remove the indicator views if we're not set to use them
531cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (indicatorUp != null && (indicators & ViewCompat.SCROLL_INDICATOR_TOP) == 0) {
532cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                contentPanel.removeView(indicatorUp);
533cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                indicatorUp = null;
534cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
535cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (indicatorDown != null && (indicators & ViewCompat.SCROLL_INDICATOR_BOTTOM) == 0) {
536cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                contentPanel.removeView(indicatorDown);
537cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                indicatorDown = null;
538cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            }
539cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
540cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            if (indicatorUp != null || indicatorDown != null) {
541cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                final View top = indicatorUp;
542cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                final View bottom = indicatorDown;
543cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
544cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                if (mMessage != null) {
545cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    // We're just showing the ScrollView, set up listener.
546cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    mScrollView.setOnScrollChangeListener(
547cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            new NestedScrollView.OnScrollChangeListener() {
548cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                @Override
549cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                public void onScrollChange(NestedScrollView v, int scrollX,
550cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                        int scrollY,
551cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                        int oldScrollX, int oldScrollY) {
552cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                    manageScrollIndicators(v, top, bottom);
553cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                }
554cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            });
555cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    // Set up the indicators following layout.
556cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    mScrollView.post(new Runnable() {
557cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        @Override
558cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        public void run() {
559cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            manageScrollIndicators(mScrollView, top, bottom);
560cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        }
561cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    });
562cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                } else if (mListView != null) {
563cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    // We're just showing the AbsListView, set up listener.
564cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
565cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        @Override
566cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        public void onScrollStateChanged(AbsListView view, int scrollState) {}
567cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
568cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        @Override
569cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        public void onScroll(AbsListView v, int firstVisibleItem,
570cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                int visibleItemCount, int totalItemCount) {
571cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            manageScrollIndicators(v, top, bottom);
572cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        }
573cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    });
574cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    // Set up the indicators following layout.
575cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    mListView.post(new Runnable() {
576cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        @Override
577cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        public void run() {
578cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            manageScrollIndicators(mListView, top, bottom);
579cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        }
580cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    });
581cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                } else {
582cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    // We don't have any content to scroll, remove the indicators.
583cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    if (top != null) {
584cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        contentPanel.removeView(top);
585cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    }
586cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    if (bottom != null) {
587cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                        contentPanel.removeView(bottom);
588cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    }
589cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                }
59019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
59119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
592cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    }
59319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
594cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    private void setupCustomContent(ViewGroup customPanel) {
59519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        final View customView;
59619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mView != null) {
59719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            customView = mView;
59819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else if (mViewLayoutResId != 0) {
59919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            final LayoutInflater inflater = LayoutInflater.from(mContext);
60019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            customView = inflater.inflate(mViewLayoutResId, customPanel, false);
60119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
60219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            customView = null;
60319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
60419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
60519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        final boolean hasCustomView = customView != null;
60619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (!hasCustomView || !canTextInput(customView)) {
60719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mWindow.setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
60819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
60919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
61019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
61119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (hasCustomView) {
61219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            final FrameLayout custom = (FrameLayout) mWindow.findViewById(R.id.custom);
61319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            custom.addView(customView, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
61419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
61519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mViewSpacingSpecified) {
61619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                custom.setPadding(
61719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight, mViewSpacingBottom);
61819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
61919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
62019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mListView != null) {
62119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                ((LinearLayout.LayoutParams) customPanel.getLayoutParams()).weight = 0;
62219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
62319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
62419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            customPanel.setVisibility(View.GONE);
62519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
62619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
62719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
628cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    private void setupTitle(ViewGroup topPanel) {
62919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mCustomTitleView != null) {
63019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            // Add the custom title view directly to the topPanel layout
63119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            LayoutParams lp = new LayoutParams(
63219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
63319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
63419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            topPanel.addView(mCustomTitleView, 0, lp);
63519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
63619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            // Hide the title template
63719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            View titleTemplate = mWindow.findViewById(R.id.title_template);
63819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            titleTemplate.setVisibility(View.GONE);
63919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
64019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mIconView = (ImageView) mWindow.findViewById(android.R.id.icon);
64119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
64219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            final boolean hasTextTitle = !TextUtils.isEmpty(mTitle);
64319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (hasTextTitle) {
64419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                // Display the title if a title is supplied, else hide it.
64519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mTitleView = (TextView) mWindow.findViewById(R.id.alertTitle);
64619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mTitleView.setText(mTitle);
64719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
64819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                // Do this last so that if the user has supplied any icons we
64919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                // use them instead of the default ones. If the user has
65019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                // specified 0 then make it disappear.
65119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mIconId != 0) {
65219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    mIconView.setImageResource(mIconId);
65319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                } else if (mIcon != null) {
65419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    mIconView.setImageDrawable(mIcon);
65519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                } else {
65619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    // Apply the padding from the icon to ensure the title is
65719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    // aligned correctly.
65819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    mTitleView.setPadding(mIconView.getPaddingLeft(),
65919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mIconView.getPaddingTop(),
66019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mIconView.getPaddingRight(),
66119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mIconView.getPaddingBottom());
66219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    mIconView.setVisibility(View.GONE);
66319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
66419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else {
66519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                // Hide the title template
66619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                final View titleTemplate = mWindow.findViewById(R.id.title_template);
66719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                titleTemplate.setVisibility(View.GONE);
66819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mIconView.setVisibility(View.GONE);
66919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                topPanel.setVisibility(View.GONE);
67019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
67119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
67219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
67319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
67419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private void setupContent(ViewGroup contentPanel) {
675cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        mScrollView = (NestedScrollView) mWindow.findViewById(R.id.scrollView);
67619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mScrollView.setFocusable(false);
677cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        mScrollView.setNestedScrollingEnabled(false);
67819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
67919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        // Special case for users that only want to display a String
680cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        mMessageView = (TextView) contentPanel.findViewById(android.R.id.message);
68119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mMessageView == null) {
68219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return;
68319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
68419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
68519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (mMessage != null) {
68619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mMessageView.setText(mMessage);
68719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
68819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mMessageView.setVisibility(View.GONE);
68919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mScrollView.removeView(mMessageView);
69019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
69119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mListView != null) {
69219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                final ViewGroup scrollParent = (ViewGroup) mScrollView.getParent();
69319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                final int childIndex = scrollParent.indexOfChild(mScrollView);
69419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                scrollParent.removeViewAt(childIndex);
69519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                scrollParent.addView(mListView, childIndex,
69619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        new LayoutParams(MATCH_PARENT, MATCH_PARENT));
69719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else {
69819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                contentPanel.setVisibility(View.GONE);
69919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
70019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
70119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
70219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
703cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    private static void manageScrollIndicators(View v, View upIndicator, View downIndicator) {
704cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (upIndicator != null) {
705cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            upIndicator.setVisibility(
706cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    ViewCompat.canScrollVertically(v, -1) ? View.VISIBLE : View.INVISIBLE);
707cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
708cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (downIndicator != null) {
709cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            downIndicator.setVisibility(
710cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    ViewCompat.canScrollVertically(v, 1) ? View.VISIBLE : View.INVISIBLE);
711cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        }
712cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    }
713cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
714cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes    private void setupButtons(ViewGroup buttonPanel) {
71519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        int BIT_BUTTON_POSITIVE = 1;
71619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        int BIT_BUTTON_NEGATIVE = 2;
71719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        int BIT_BUTTON_NEUTRAL = 4;
71819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        int whichButtons = 0;
719cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        mButtonPositive = (Button) buttonPanel.findViewById(android.R.id.button1);
72019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mButtonPositive.setOnClickListener(mButtonHandler);
72119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
72219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (TextUtils.isEmpty(mButtonPositiveText)) {
72319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonPositive.setVisibility(View.GONE);
72419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
72519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonPositive.setText(mButtonPositiveText);
72619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonPositive.setVisibility(View.VISIBLE);
72719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            whichButtons = whichButtons | BIT_BUTTON_POSITIVE;
72819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
72919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
730cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        mButtonNegative = (Button) buttonPanel.findViewById(android.R.id.button2);
73119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mButtonNegative.setOnClickListener(mButtonHandler);
73219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
73319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (TextUtils.isEmpty(mButtonNegativeText)) {
73419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonNegative.setVisibility(View.GONE);
73519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
73619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonNegative.setText(mButtonNegativeText);
73719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonNegative.setVisibility(View.VISIBLE);
73819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
73919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            whichButtons = whichButtons | BIT_BUTTON_NEGATIVE;
74019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
74119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
742cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        mButtonNeutral = (Button) buttonPanel.findViewById(android.R.id.button3);
74319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        mButtonNeutral.setOnClickListener(mButtonHandler);
74419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
74519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        if (TextUtils.isEmpty(mButtonNeutralText)) {
74619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonNeutral.setVisibility(View.GONE);
74719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        } else {
74819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonNeutral.setText(mButtonNeutralText);
74919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mButtonNeutral.setVisibility(View.VISIBLE);
75019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
75119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            whichButtons = whichButtons | BIT_BUTTON_NEUTRAL;
75219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
75319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
754cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        final boolean hasButtons = whichButtons != 0;
755cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes        if (!hasButtons) {
756cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            buttonPanel.setVisibility(View.GONE);
75719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
75819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
75919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
76019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    public static class AlertParams {
76119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public final Context mContext;
76219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public final LayoutInflater mInflater;
76319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
76419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mIconId = 0;
76519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public Drawable mIcon;
76619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mIconAttrId = 0;
76719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CharSequence mTitle;
76819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public View mCustomTitleView;
76919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CharSequence mMessage;
77019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CharSequence mPositiveButtonText;
77119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnClickListener mPositiveButtonListener;
77219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CharSequence mNegativeButtonText;
77319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnClickListener mNegativeButtonListener;
77419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CharSequence mNeutralButtonText;
77519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnClickListener mNeutralButtonListener;
77619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean mCancelable;
77719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnCancelListener mOnCancelListener;
77819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnDismissListener mOnDismissListener;
77919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnKeyListener mOnKeyListener;
78019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CharSequence[] mItems;
78119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public ListAdapter mAdapter;
78219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnClickListener mOnClickListener;
78319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mViewLayoutResId;
78419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public View mView;
78519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mViewSpacingLeft;
78619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mViewSpacingTop;
78719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mViewSpacingRight;
78819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mViewSpacingBottom;
78919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean mViewSpacingSpecified = false;
79019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean[] mCheckedItems;
79119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean mIsMultiChoice;
79219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean mIsSingleChoice;
79319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public int mCheckedItem = -1;
79419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public DialogInterface.OnMultiChoiceClickListener mOnCheckboxClickListener;
79519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public Cursor mCursor;
79619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public String mLabelColumn;
79719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public String mIsCheckedColumn;
79819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean mForceInverseBackground;
79919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public AdapterView.OnItemSelectedListener mOnItemSelectedListener;
80019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public OnPrepareListViewListener mOnPrepareListViewListener;
80119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean mRecycleOnMeasure = true;
80219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
80319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        /**
80419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes         * Interface definition for a callback to be invoked before the ListView
80519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes         * will be bound to an adapter.
80619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes         */
80719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public interface OnPrepareListViewListener {
80819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
80919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            /**
81019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes             * Called before the ListView is bound to an adapter.
81119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes             * @param listView The ListView that will be shown in the dialog.
81219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes             */
81319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            void onPrepareListView(ListView listView);
81419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
81519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
81619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public AlertParams(Context context) {
81719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mContext = context;
81819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mCancelable = true;
81919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
82019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
82119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
82219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public void apply(AlertController dialog) {
82319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mCustomTitleView != null) {
82419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setCustomTitle(mCustomTitleView);
82519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else {
82619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mTitle != null) {
82719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    dialog.setTitle(mTitle);
82819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
82919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mIcon != null) {
83019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    dialog.setIcon(mIcon);
83119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
83219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mIconId != 0) {
83319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    dialog.setIcon(mIconId);
83419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
83519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mIconAttrId != 0) {
83619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    dialog.setIcon(dialog.getIconAttributeResId(mIconAttrId));
83719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
83819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
83919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mMessage != null) {
84019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setMessage(mMessage);
84119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
84219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mPositiveButtonText != null) {
84319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setButton(DialogInterface.BUTTON_POSITIVE, mPositiveButtonText,
84419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        mPositiveButtonListener, null);
84519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
84619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mNegativeButtonText != null) {
84719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setButton(DialogInterface.BUTTON_NEGATIVE, mNegativeButtonText,
84819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        mNegativeButtonListener, null);
84919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
85019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mNeutralButtonText != null) {
85119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setButton(DialogInterface.BUTTON_NEUTRAL, mNeutralButtonText,
85219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        mNeutralButtonListener, null);
85319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
85419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            // For a list, the client can either supply an array of items or an
85519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            // adapter or a cursor
85619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if ((mItems != null) || (mCursor != null) || (mAdapter != null)) {
85719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                createListView(dialog);
85819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
85919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mView != null) {
86019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mViewSpacingSpecified) {
86119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    dialog.setView(mView, mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight,
86219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mViewSpacingBottom);
86319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                } else {
86419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    dialog.setView(mView);
86519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
86619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else if (mViewLayoutResId != 0) {
86719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setView(mViewLayoutResId);
86819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
86919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
87019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            /*
87119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            dialog.setCancelable(mCancelable);
87219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            dialog.setOnCancelListener(mOnCancelListener);
87319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mOnKeyListener != null) {
87419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                dialog.setOnKeyListener(mOnKeyListener);
87519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
87619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            */
87719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
87819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
87919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        private void createListView(final AlertController dialog) {
88019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            final ListView listView = (ListView) mInflater.inflate(dialog.mListLayout, null);
881cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes            final ListAdapter adapter;
88219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
88319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mIsMultiChoice) {
88419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                if (mCursor == null) {
88519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    adapter = new ArrayAdapter<CharSequence>(
88619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mContext, dialog.mMultiChoiceItemLayout, android.R.id.text1, mItems) {
88719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        @Override
88819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        public View getView(int position, View convertView, ViewGroup parent) {
88919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            View view = super.getView(position, convertView, parent);
89019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            if (mCheckedItems != null) {
89119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                boolean isItemChecked = mCheckedItems[position];
89219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                if (isItemChecked) {
89319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                    listView.setItemChecked(position, true);
89419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                }
89519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            }
89619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            return view;
89719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        }
89819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    };
89919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                } else {
90019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    adapter = new CursorAdapter(mContext, mCursor, false) {
90119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        private final int mLabelIndex;
90219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        private final int mIsCheckedIndex;
90319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
90419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        {
90519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            final Cursor cursor = getCursor();
90619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mLabelIndex = cursor.getColumnIndexOrThrow(mLabelColumn);
90719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mIsCheckedIndex = cursor.getColumnIndexOrThrow(mIsCheckedColumn);
90819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        }
90919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
91019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        @Override
91119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        public void bindView(View view, Context context, Cursor cursor) {
912cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            CheckedTextView text = (CheckedTextView) view.findViewById(
913cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                                    android.R.id.text1);
91419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            text.setText(cursor.getString(mLabelIndex));
91519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            listView.setItemChecked(cursor.getPosition(),
91619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                    cursor.getInt(mIsCheckedIndex) == 1);
91719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        }
91819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
91919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        @Override
92019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        public View newView(Context context, Cursor cursor, ViewGroup parent) {
92119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            return mInflater.inflate(dialog.mMultiChoiceItemLayout,
92219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                    parent, false);
92319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        }
92419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
92519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    };
92619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
92719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else {
928cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                final int layout;
929cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                if (mIsSingleChoice) {
930cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    layout = dialog.mSingleChoiceItemLayout;
931cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                } else {
932cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    layout = dialog.mListItemLayout;
933cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                }
934cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes
935cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                if (mCursor != null) {
936cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    adapter = new SimpleCursorAdapter(mContext, layout, mCursor,
937cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                            new String[] { mLabelColumn }, new int[] { android.R.id.text1 });
938cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                } else if (mAdapter != null) {
939cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    adapter = mAdapter;
94019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                } else {
941cc82b3ee0c53b2f2da75b7fda5fe4b8f5af5dc1cChris Banes                    adapter = new CheckedItemAdapter(mContext, layout, android.R.id.text1, mItems);
94219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                }
94319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
94419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
94519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mOnPrepareListViewListener != null) {
94619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                mOnPrepareListViewListener.onPrepareListView(listView);
94719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
94819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
94919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            /* Don't directly set the adapter on the ListView as we might
95019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes             * want to add a footer to the ListView later.
95119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes             */
95219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            dialog.mAdapter = adapter;
95319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            dialog.mCheckedItem = mCheckedItem;
95419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
95519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mOnClickListener != null) {
95619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                listView.setOnItemClickListener(new OnItemClickListener() {
95719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    @Override
95819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
95919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        mOnClickListener.onClick(dialog.mDialog, position);
96019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        if (!mIsSingleChoice) {
96119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            dialog.mDialog.dismiss();
96219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        }
96319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    }
96419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                });
96519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else if (mOnCheckboxClickListener != null) {
96619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                listView.setOnItemClickListener(new OnItemClickListener() {
96719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    @Override
96819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
96919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        if (mCheckedItems != null) {
97019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                            mCheckedItems[position] = listView.isItemChecked(position);
97119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        }
97219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                        mOnCheckboxClickListener.onClick(
97319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                                dialog.mDialog, position, listView.isItemChecked(position));
97419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                    }
97519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                });
97619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
97719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
97819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            // Attach a given OnItemSelectedListener to the ListView
97919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mOnItemSelectedListener != null) {
98019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                listView.setOnItemSelectedListener(mOnItemSelectedListener);
98119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
98219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
98319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            if (mIsSingleChoice) {
98419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
98519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            } else if (mIsMultiChoice) {
98619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
98719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            }
98819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            dialog.mListView = listView;
98919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
99019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
99119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
99219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    private static class CheckedItemAdapter extends ArrayAdapter<CharSequence> {
99319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public CheckedItemAdapter(Context context, int resource, int textViewResourceId,
99419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes                CharSequence[] objects) {
99519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            super(context, resource, textViewResourceId, objects);
99619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
99719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
99819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        @Override
99919eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public boolean hasStableIds() {
100019eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return true;
100119eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
100219eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes
100319eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        @Override
100419eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        public long getItemId(int position) {
100519eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes            return position;
100619eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes        }
100719eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes    }
100819eaf14cb3cca613f984a32be2fab2534427fb29Chris Banes}
1009