AlertControllerpublic class AlertController extends Object
Fields Summary |
---|
private final android.content.Context | mContext | private final android.content.DialogInterface | mDialogInterface | private final android.view.Window | mWindow | private CharSequence | mTitle | private CharSequence | mMessage | private android.widget.ListView | mListView | private android.view.View | mView | private int | mViewLayoutResId | private int | mViewSpacingLeft | private int | mViewSpacingTop | private int | mViewSpacingRight | private int | mViewSpacingBottom | private boolean | mViewSpacingSpecified | private android.widget.Button | mButtonPositive | private CharSequence | mButtonPositiveText | private android.os.Message | mButtonPositiveMessage | private android.widget.Button | mButtonNegative | private CharSequence | mButtonNegativeText | private android.os.Message | mButtonNegativeMessage | private android.widget.Button | mButtonNeutral | private CharSequence | mButtonNeutralText | private android.os.Message | mButtonNeutralMessage | private android.widget.ScrollView | mScrollView | private int | mIconId | private android.graphics.drawable.Drawable | mIcon | private android.widget.ImageView | mIconView | private android.widget.TextView | mTitleView | private android.widget.TextView | mMessageView | private android.view.View | mCustomTitleView | private boolean | mForceInverseBackground | private android.widget.ListAdapter | mAdapter | private int | mCheckedItem | private int | mAlertDialogLayout | private int | mButtonPanelSideLayout | private int | mListLayout | private int | mMultiChoiceItemLayout | private int | mSingleChoiceItemLayout | private int | mListItemLayout | private int | mButtonPanelLayoutHint | private android.os.Handler | mHandler | private final View.OnClickListener | mButtonHandler |
Constructors Summary |
---|
public AlertController(android.content.Context context, android.content.DialogInterface di, android.view.Window window)
mContext = context;
mDialogInterface = di;
mWindow = window;
mHandler = new ButtonHandler(di);
TypedArray a = context.obtainStyledAttributes(null,
com.android.internal.R.styleable.AlertDialog,
com.android.internal.R.attr.alertDialogStyle, 0);
mAlertDialogLayout = a.getResourceId(com.android.internal.R.styleable.AlertDialog_layout,
com.android.internal.R.layout.alert_dialog);
mButtonPanelSideLayout = a.getResourceId(
com.android.internal.R.styleable.AlertDialog_buttonPanelSideLayout, 0);
mListLayout = a.getResourceId(
com.android.internal.R.styleable.AlertDialog_listLayout,
com.android.internal.R.layout.select_dialog);
mMultiChoiceItemLayout = a.getResourceId(
com.android.internal.R.styleable.AlertDialog_multiChoiceItemLayout,
com.android.internal.R.layout.select_dialog_multichoice);
mSingleChoiceItemLayout = a.getResourceId(
com.android.internal.R.styleable.AlertDialog_singleChoiceItemLayout,
com.android.internal.R.layout.select_dialog_singlechoice);
mListItemLayout = a.getResourceId(
com.android.internal.R.styleable.AlertDialog_listItemLayout,
com.android.internal.R.layout.select_dialog_item);
a.recycle();
|
Methods Summary |
---|
static boolean | canTextInput(android.view.View v)
if (v.onCheckIsTextEditor()) {
return true;
}
if (!(v instanceof ViewGroup)) {
return false;
}
ViewGroup vg = (ViewGroup)v;
int i = vg.getChildCount();
while (i > 0) {
i--;
v = vg.getChildAt(i);
if (canTextInput(v)) {
return true;
}
}
return false;
| private void | centerButton(android.widget.Button button)
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) button.getLayoutParams();
params.gravity = Gravity.CENTER_HORIZONTAL;
params.weight = 0.5f;
button.setLayoutParams(params);
View leftSpacer = mWindow.findViewById(R.id.leftSpacer);
if (leftSpacer != null) {
leftSpacer.setVisibility(View.VISIBLE);
}
View rightSpacer = mWindow.findViewById(R.id.rightSpacer);
if (rightSpacer != null) {
rightSpacer.setVisibility(View.VISIBLE);
}
| public android.widget.Button | getButton(int whichButton)
switch (whichButton) {
case DialogInterface.BUTTON_POSITIVE:
return mButtonPositive;
case DialogInterface.BUTTON_NEGATIVE:
return mButtonNegative;
case DialogInterface.BUTTON_NEUTRAL:
return mButtonNeutral;
default:
return null;
}
| public int | getIconAttributeResId(int attrId)
TypedValue out = new TypedValue();
mContext.getTheme().resolveAttribute(attrId, out, true);
return out.resourceId;
| public android.widget.ListView | getListView()
return mListView;
| public void | installContent()
/* We use a custom title so never request a window title */
mWindow.requestFeature(Window.FEATURE_NO_TITLE);
int contentView = selectContentView();
mWindow.setContentView(contentView);
setupView();
setupDecor();
| private static void | manageScrollIndicators(android.view.View v, android.view.View upIndicator, android.view.View downIndicator)
if (upIndicator != null) {
upIndicator.setVisibility(v.canScrollVertically(-1) ? View.VISIBLE : View.INVISIBLE);
}
if (downIndicator != null) {
downIndicator.setVisibility(v.canScrollVertically(1) ? View.VISIBLE : View.INVISIBLE);
}
| public boolean | onKeyDown(int keyCode, android.view.KeyEvent event)
return mScrollView != null && mScrollView.executeKeyEvent(event);
| public boolean | onKeyUp(int keyCode, android.view.KeyEvent event)
return mScrollView != null && mScrollView.executeKeyEvent(event);
| private int | selectContentView()
if (mButtonPanelSideLayout == 0) {
return mAlertDialogLayout;
}
if (mButtonPanelLayoutHint == AlertDialog.LAYOUT_HINT_SIDE) {
return mButtonPanelSideLayout;
}
// TODO: use layout hint side for long messages/lists
return mAlertDialogLayout;
| private void | setBackground(android.content.res.TypedArray a, android.view.View topPanel, android.view.View contentPanel, android.view.View customPanel, android.view.View buttonPanel, boolean hasTitle, boolean hasCustomView, boolean hasButtons)
int fullDark = 0;
int topDark = 0;
int centerDark = 0;
int bottomDark = 0;
int fullBright = 0;
int topBright = 0;
int centerBright = 0;
int bottomBright = 0;
int bottomMedium = 0;
// If the needsDefaultBackgrounds attribute is set, we know we're
// inheriting from a framework style.
final boolean needsDefaultBackgrounds = a.getBoolean(
R.styleable.AlertDialog_needsDefaultBackgrounds, true);
if (needsDefaultBackgrounds) {
fullDark = R.drawable.popup_full_dark;
topDark = R.drawable.popup_top_dark;
centerDark = R.drawable.popup_center_dark;
bottomDark = R.drawable.popup_bottom_dark;
fullBright = R.drawable.popup_full_bright;
topBright = R.drawable.popup_top_bright;
centerBright = R.drawable.popup_center_bright;
bottomBright = R.drawable.popup_bottom_bright;
bottomMedium = R.drawable.popup_bottom_medium;
}
topBright = a.getResourceId(R.styleable.AlertDialog_topBright, topBright);
topDark = a.getResourceId(R.styleable.AlertDialog_topDark, topDark);
centerBright = a.getResourceId(R.styleable.AlertDialog_centerBright, centerBright);
centerDark = a.getResourceId(R.styleable.AlertDialog_centerDark, centerDark);
/* We now set the background of all of the sections of the alert.
* First collect together each section that is being displayed along
* with whether it is on a light or dark background, then run through
* them setting their backgrounds. This is complicated because we need
* to correctly use the full, top, middle, and bottom graphics depending
* on how many views they are and where they appear.
*/
final View[] views = new View[4];
final boolean[] light = new boolean[4];
View lastView = null;
boolean lastLight = false;
int pos = 0;
if (hasTitle) {
views[pos] = topPanel;
light[pos] = false;
pos++;
}
/* The contentPanel displays either a custom text message or
* a ListView. If it's text we should use the dark background
* for ListView we should use the light background. If neither
* are there the contentPanel will be hidden so set it as null.
*/
views[pos] = contentPanel.getVisibility() == View.GONE ? null : contentPanel;
light[pos] = mListView != null;
pos++;
if (hasCustomView) {
views[pos] = customPanel;
light[pos] = mForceInverseBackground;
pos++;
}
if (hasButtons) {
views[pos] = buttonPanel;
light[pos] = true;
}
boolean setView = false;
for (pos = 0; pos < views.length; pos++) {
final View v = views[pos];
if (v == null) {
continue;
}
if (lastView != null) {
if (!setView) {
lastView.setBackgroundResource(lastLight ? topBright : topDark);
} else {
lastView.setBackgroundResource(lastLight ? centerBright : centerDark);
}
setView = true;
}
lastView = v;
lastLight = light[pos];
}
if (lastView != null) {
if (setView) {
bottomBright = a.getResourceId(R.styleable.AlertDialog_bottomBright, bottomBright);
bottomMedium = a.getResourceId(R.styleable.AlertDialog_bottomMedium, bottomMedium);
bottomDark = a.getResourceId(R.styleable.AlertDialog_bottomDark, bottomDark);
// ListViews will use the Bright background, but buttons use the
// Medium background.
lastView.setBackgroundResource(
lastLight ? (hasButtons ? bottomMedium : bottomBright) : bottomDark);
} else {
fullBright = a.getResourceId(R.styleable.AlertDialog_fullBright, fullBright);
fullDark = a.getResourceId(R.styleable.AlertDialog_fullDark, fullDark);
lastView.setBackgroundResource(lastLight ? fullBright : fullDark);
}
}
final ListView listView = mListView;
if (listView != null && mAdapter != null) {
listView.setAdapter(mAdapter);
final int checkedItem = mCheckedItem;
if (checkedItem > -1) {
listView.setItemChecked(checkedItem, true);
listView.setSelection(checkedItem);
}
}
| public void | setButton(int whichButton, java.lang.CharSequence text, DialogInterface.OnClickListener listener, android.os.Message msg)Sets a click listener or a message to be sent when the button is clicked.
You only need to pass one of {@code listener} or {@code msg}.
if (msg == null && listener != null) {
msg = mHandler.obtainMessage(whichButton, listener);
}
switch (whichButton) {
case DialogInterface.BUTTON_POSITIVE:
mButtonPositiveText = text;
mButtonPositiveMessage = msg;
break;
case DialogInterface.BUTTON_NEGATIVE:
mButtonNegativeText = text;
mButtonNegativeMessage = msg;
break;
case DialogInterface.BUTTON_NEUTRAL:
mButtonNeutralText = text;
mButtonNeutralMessage = msg;
break;
default:
throw new IllegalArgumentException("Button does not exist");
}
| public void | setButtonPanelLayoutHint(int layoutHint)Sets a hint for the best button panel layout.
mButtonPanelLayoutHint = layoutHint;
| public void | setCustomTitle(android.view.View customTitleView)
mCustomTitleView = customTitleView;
| public void | setIcon(int resId)Specifies the icon to display next to the alert title.
mIcon = null;
mIconId = resId;
if (mIconView != null) {
if (resId != 0) {
mIconView.setImageResource(mIconId);
} else {
mIconView.setVisibility(View.GONE);
}
}
| public void | setIcon(android.graphics.drawable.Drawable icon)Specifies the icon to display next to the alert title.
mIcon = icon;
mIconId = 0;
if (mIconView != null) {
if (icon != null) {
mIconView.setImageDrawable(icon);
} else {
mIconView.setVisibility(View.GONE);
}
}
| public void | setInverseBackgroundForced(boolean forceInverseBackground)
mForceInverseBackground = forceInverseBackground;
| public void | setMessage(java.lang.CharSequence message)
mMessage = message;
if (mMessageView != null) {
mMessageView.setText(message);
}
| public void | setTitle(java.lang.CharSequence title)
mTitle = title;
if (mTitleView != null) {
mTitleView.setText(title);
}
| public void | setView(android.view.View view)Set the view to display in the dialog.
mView = view;
mViewLayoutResId = 0;
mViewSpacingSpecified = false;
| public void | setView(android.view.View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom)Set the view to display in the dialog along with the spacing around that view
mView = view;
mViewLayoutResId = 0;
mViewSpacingSpecified = true;
mViewSpacingLeft = viewSpacingLeft;
mViewSpacingTop = viewSpacingTop;
mViewSpacingRight = viewSpacingRight;
mViewSpacingBottom = viewSpacingBottom;
| public void | setView(int layoutResId)Set the view resource to display in the dialog.
mView = null;
mViewLayoutResId = layoutResId;
mViewSpacingSpecified = false;
| private boolean | setupButtons()
int BIT_BUTTON_POSITIVE = 1;
int BIT_BUTTON_NEGATIVE = 2;
int BIT_BUTTON_NEUTRAL = 4;
int whichButtons = 0;
mButtonPositive = (Button) mWindow.findViewById(R.id.button1);
mButtonPositive.setOnClickListener(mButtonHandler);
if (TextUtils.isEmpty(mButtonPositiveText)) {
mButtonPositive.setVisibility(View.GONE);
} else {
mButtonPositive.setText(mButtonPositiveText);
mButtonPositive.setVisibility(View.VISIBLE);
whichButtons = whichButtons | BIT_BUTTON_POSITIVE;
}
mButtonNegative = (Button) mWindow.findViewById(R.id.button2);
mButtonNegative.setOnClickListener(mButtonHandler);
if (TextUtils.isEmpty(mButtonNegativeText)) {
mButtonNegative.setVisibility(View.GONE);
} else {
mButtonNegative.setText(mButtonNegativeText);
mButtonNegative.setVisibility(View.VISIBLE);
whichButtons = whichButtons | BIT_BUTTON_NEGATIVE;
}
mButtonNeutral = (Button) mWindow.findViewById(R.id.button3);
mButtonNeutral.setOnClickListener(mButtonHandler);
if (TextUtils.isEmpty(mButtonNeutralText)) {
mButtonNeutral.setVisibility(View.GONE);
} else {
mButtonNeutral.setText(mButtonNeutralText);
mButtonNeutral.setVisibility(View.VISIBLE);
whichButtons = whichButtons | BIT_BUTTON_NEUTRAL;
}
if (shouldCenterSingleButton(mContext)) {
/*
* If we only have 1 button it should be centered on the layout and
* expand to fill 50% of the available space.
*/
if (whichButtons == BIT_BUTTON_POSITIVE) {
centerButton(mButtonPositive);
} else if (whichButtons == BIT_BUTTON_NEGATIVE) {
centerButton(mButtonNegative);
} else if (whichButtons == BIT_BUTTON_NEUTRAL) {
centerButton(mButtonNeutral);
}
}
return whichButtons != 0;
| private void | setupContent(android.view.ViewGroup contentPanel)
mScrollView = (ScrollView) mWindow.findViewById(R.id.scrollView);
mScrollView.setFocusable(false);
// Special case for users that only want to display a String
mMessageView = (TextView) mWindow.findViewById(R.id.message);
if (mMessageView == null) {
return;
}
if (mMessage != null) {
mMessageView.setText(mMessage);
} else {
mMessageView.setVisibility(View.GONE);
mScrollView.removeView(mMessageView);
if (mListView != null) {
final ViewGroup scrollParent = (ViewGroup) mScrollView.getParent();
final int childIndex = scrollParent.indexOfChild(mScrollView);
scrollParent.removeViewAt(childIndex);
scrollParent.addView(mListView, childIndex,
new LayoutParams(MATCH_PARENT, MATCH_PARENT));
} else {
contentPanel.setVisibility(View.GONE);
}
}
// Set up scroll indicators (if present).
final View indicatorUp = mWindow.findViewById(R.id.scrollIndicatorUp);
final View indicatorDown = mWindow.findViewById(R.id.scrollIndicatorDown);
if (indicatorUp != null || indicatorDown != null) {
if (mMessage != null) {
// We're just showing the ScrollView, set up listener.
mScrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
@Override
public void onScrollChange(View v, int scrollX, int scrollY,
int oldScrollX, int oldScrollY) {
manageScrollIndicators(v, indicatorUp, indicatorDown);
}
});
// Set up the indicators following layout.
mScrollView.post(new Runnable() {
@Override
public void run() {
manageScrollIndicators(mScrollView, indicatorUp, indicatorDown);
}
});
} else if (mListView != null) {
// We're just showing the AbsListView, set up listener.
mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// That's cool, I guess?
}
@Override
public void onScroll(AbsListView v, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
manageScrollIndicators(v, indicatorUp, indicatorDown);
}
});
// Set up the indicators following layout.
mListView.post(new Runnable() {
@Override
public void run() {
manageScrollIndicators(mListView, indicatorUp, indicatorDown);
}
});
} else {
// We don't have any content to scroll, remove the indicators.
if (indicatorUp != null) {
contentPanel.removeView(indicatorUp);
}
if (indicatorDown != null) {
contentPanel.removeView(indicatorDown);
}
}
}
| private void | setupDecor()
final View decor = mWindow.getDecorView();
final View parent = mWindow.findViewById(R.id.parentPanel);
if (parent != null && decor != null) {
decor.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
@Override
public WindowInsets onApplyWindowInsets(View view, WindowInsets insets) {
if (insets.isRound()) {
// TODO: Get the padding as a function of the window size.
int roundOffset = mContext.getResources().getDimensionPixelOffset(
R.dimen.alert_dialog_round_padding);
parent.setPadding(roundOffset, roundOffset, roundOffset, roundOffset);
}
return insets.consumeSystemWindowInsets();
}
});
decor.setFitsSystemWindows(true);
decor.requestApplyInsets();
}
| private boolean | setupTitle(android.view.ViewGroup topPanel)
boolean hasTitle = true;
if (mCustomTitleView != null) {
// Add the custom title view directly to the topPanel layout
LayoutParams lp = new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
topPanel.addView(mCustomTitleView, 0, lp);
// Hide the title template
View titleTemplate = mWindow.findViewById(R.id.title_template);
titleTemplate.setVisibility(View.GONE);
} else {
mIconView = (ImageView) mWindow.findViewById(R.id.icon);
final boolean hasTextTitle = !TextUtils.isEmpty(mTitle);
if (hasTextTitle) {
// Display the title if a title is supplied, else hide it.
mTitleView = (TextView) mWindow.findViewById(R.id.alertTitle);
mTitleView.setText(mTitle);
// Do this last so that if the user has supplied any icons we
// use them instead of the default ones. If the user has
// specified 0 then make it disappear.
if (mIconId != 0) {
mIconView.setImageResource(mIconId);
} else if (mIcon != null) {
mIconView.setImageDrawable(mIcon);
} else {
// Apply the padding from the icon to ensure the title is
// aligned correctly.
mTitleView.setPadding(mIconView.getPaddingLeft(),
mIconView.getPaddingTop(),
mIconView.getPaddingRight(),
mIconView.getPaddingBottom());
mIconView.setVisibility(View.GONE);
}
} else {
// Hide the title template
final View titleTemplate = mWindow.findViewById(R.id.title_template);
titleTemplate.setVisibility(View.GONE);
mIconView.setVisibility(View.GONE);
topPanel.setVisibility(View.GONE);
hasTitle = false;
}
}
return hasTitle;
| private void | setupView()
final ViewGroup contentPanel = (ViewGroup) mWindow.findViewById(R.id.contentPanel);
setupContent(contentPanel);
final boolean hasButtons = setupButtons();
final ViewGroup topPanel = (ViewGroup) mWindow.findViewById(R.id.topPanel);
final TypedArray a = mContext.obtainStyledAttributes(
null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);
final boolean hasTitle = setupTitle(topPanel);
final View buttonPanel = mWindow.findViewById(R.id.buttonPanel);
if (!hasButtons) {
buttonPanel.setVisibility(View.GONE);
final View spacer = mWindow.findViewById(R.id.textSpacerNoButtons);
if (spacer != null) {
spacer.setVisibility(View.VISIBLE);
}
mWindow.setCloseOnTouchOutsideIfNotSet(true);
}
final FrameLayout customPanel = (FrameLayout) mWindow.findViewById(R.id.customPanel);
final View customView;
if (mView != null) {
customView = mView;
} else if (mViewLayoutResId != 0) {
final LayoutInflater inflater = LayoutInflater.from(mContext);
customView = inflater.inflate(mViewLayoutResId, customPanel, false);
} else {
customView = null;
}
final boolean hasCustomView = customView != null;
if (!hasCustomView || !canTextInput(customView)) {
mWindow.setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
}
if (hasCustomView) {
final FrameLayout custom = (FrameLayout) mWindow.findViewById(R.id.custom);
custom.addView(customView, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
if (mViewSpacingSpecified) {
custom.setPadding(
mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight, mViewSpacingBottom);
}
if (mListView != null) {
((LinearLayout.LayoutParams) customPanel.getLayoutParams()).weight = 0;
}
} else {
customPanel.setVisibility(View.GONE);
}
// Only display the divider if we have a title and a custom view or a
// message.
if (hasTitle) {
final View divider;
if (mMessage != null || customView != null || mListView != null) {
divider = mWindow.findViewById(R.id.titleDivider);
} else {
divider = mWindow.findViewById(R.id.titleDividerTop);
}
if (divider != null) {
divider.setVisibility(View.VISIBLE);
}
}
setBackground(a, topPanel, contentPanel, customPanel, buttonPanel, hasTitle, hasCustomView,
hasButtons);
a.recycle();
| private static boolean | shouldCenterSingleButton(android.content.Context context)
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogCenterButtons,
outValue, true);
return outValue.data != 0;
|
|