package com.WazaBe.HoloEverywhere; import java.util.Map.Entry; import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.content.res.TypedArray; import android.database.Cursor; import android.graphics.drawable.Drawable; import android.os.Build.VERSION; import android.util.TypedValue; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager.LayoutParams; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; public class AlertDialog extends android.app.AlertDialog { @SuppressLint("NewApi") public static class Builder extends android.app.AlertDialog.Builder { private static class InternalListListener implements OnItemClickListener, OnItemSelectedListener { private final Builder builder; private OnClickListener listener; private OnMultiChoiceClickListener multiListener; public InternalListListener(OnClickListener listener, Builder builder) { this.listener = listener; this.builder = builder; } public InternalListListener( OnMultiChoiceClickListener multiListener, Builder builder) { this.multiListener = multiListener; this.builder = builder; } @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { if (listener != null) { listener.onClick(builder.getLastDialog(), position); } } @Override public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) { if (multiListener != null) { multiListener .onClick(builder.getLastDialog(), position, ((AbsListView) adapterView) .isItemChecked(position)); } } @Override public void onNothingSelected(AdapterView<?> arg0) { } } private ButtonEntry buttonNegative, buttonNeutral, buttonPositive; private boolean cancelable = true; private final Context context; private Drawable icon; private AlertDialog lastDialog; private OnCancelListener onCancelListener; private CharSequence title, message; private boolean useNative = false; private View view; private int viewSpacingLeft = 0, viewSpacingTop = 0, viewSpacingRight = 0, viewSpacingBottom = 0; public Builder(Context context) { this(context, useNative()); } public Builder(Context context, boolean useNative) { super(context); setUseNative(useNative); this.context = context; } public Context context() { return context; } @Override public AlertDialog create() { AlertDialog dialog = new AlertDialog(context(), isCancelable(), getOnCancelListener(), isUseNative()); if (title != null) { dialog.setTitle(title); } if (message != null) { dialog.setMessage(message); } if (icon != null) { dialog.setIcon(icon); } if (getPositiveButton() != null) { dialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton().getKey(), getPositiveButton() .getValue()); } if (getNeutralButton() != null) { dialog.setButton(DialogInterface.BUTTON_NEUTRAL, getNeutralButton().getKey(), getNeutralButton() .getValue()); } if (getNegativeButton() != null) { dialog.setButton(DialogInterface.BUTTON_NEGATIVE, getNegativeButton().getKey(), getNegativeButton() .getValue()); } if (getView() != null) { dialog.setView(getView(), getViewSpacingLeft(), getViewSpacingTop(), getViewSpacingRight(), getViewSpacingBottom()); } return lastDialog = dialog; } public AlertDialog getLastDialog() { return lastDialog; } public LayoutInflater getLayoutInflater() { return LayoutInflater.from(context); } public CharSequence getMessage() { return message; } public ButtonEntry getNegativeButton() { return buttonNegative; } public ButtonEntry getNeutralButton() { return buttonNeutral; } public OnCancelListener getOnCancelListener() { return onCancelListener; } public ButtonEntry getPositiveButton() { return buttonPositive; } public CharSequence getTitle() { return title; } public View getView() { return view; } public int getViewSpacingBottom() { return viewSpacingBottom; } public int getViewSpacingLeft() { return viewSpacingLeft; } public int getViewSpacingRight() { return viewSpacingRight; } public int getViewSpacingTop() { return viewSpacingTop; } public boolean isCancelable() { return cancelable; } public boolean isUseNative() { return useNative; } public Builder removeNegativeButton() { buttonNegative = null; return this; } public Builder removeNeutralButton() { buttonNeutral = null; return this; } public Builder removePositiveButton() { buttonPositive = null; return this; } @Override public Builder setCancelable(boolean cancelable) { this.cancelable = cancelable; return this; } @Override public Builder setIcon(Drawable icon) { this.icon = icon; return this; } @Override public Builder setIcon(int iconId) { return setIcon(context().getResources().getDrawable(iconId)); } @Override public Builder setItems(CharSequence[] items, OnClickListener listener) { return setItems(new ArrayAdapter<CharSequence>(context(), android.R.layout.simple_list_item_1, items), -1, listener, AbsListView.CHOICE_MODE_NONE); } @Override public Builder setItems(int itemsId, OnClickListener listener) { return setItems(ArrayAdapter.createFromResource(context(), itemsId, android.R.layout.simple_list_item_1), -1, listener, AbsListView.CHOICE_MODE_NONE); } public Builder setItems(ListAdapter adapter, boolean[] checkedItems, OnMultiChoiceClickListener listener) { ListView list = new ListView(context()); list.setAdapter(adapter); if (listener != null) { list.setOnItemSelectedListener(new InternalListListener( listener, this)); } for (int i = 0; i < checkedItems.length; i++) { list.setItemChecked(i, checkedItems[i]); } list.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); return setView(list); } public Builder setItems(ListAdapter adapter, int checkedItem, OnClickListener listener, int choiceMode) { ListView list = new ListView(context()); list.setAdapter(adapter); if (listener != null) { list.setOnItemClickListener(new InternalListListener(listener, this)); } if (checkedItem >= 0) { list.setSelection(checkedItem); } list.setChoiceMode(choiceMode); return setView(list); } @Override public Builder setMessage(CharSequence message) { this.message = message; return this; } @Override public Builder setMessage(int messageId) { return setMessage(context().getText(messageId)); } @Override public Builder setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, OnMultiChoiceClickListener listener) { return setItems(new ArrayAdapter<CharSequence>(context(), android.R.layout.simple_list_item_multiple_choice, items), checkedItems, listener); } @Override public Builder setMultiChoiceItems(Cursor cursor, String isCheckedColumn, String labelColumn, OnMultiChoiceClickListener listener) { throw new RuntimeException( "setMultiChoiceItems with Cursor temporary not supported"); } @Override public Builder setMultiChoiceItems(int itemsId, boolean[] checkedItems, OnMultiChoiceClickListener listener) { return setItems( ArrayAdapter.createFromResource(context(), android.R.layout.simple_list_item_multiple_choice, itemsId), checkedItems, listener); } @Override public Builder setNegativeButton(CharSequence text, OnClickListener listener) { buttonNegative = new ButtonEntry(text, listener); return this; } @Override public Builder setNegativeButton(int resId, OnClickListener listener) { return setNegativeButton(context().getText(resId), listener); } @Override public Builder setNeutralButton(CharSequence text, OnClickListener listener) { buttonNeutral = new ButtonEntry(text, listener); return this; } @Override public Builder setNeutralButton(int resId, OnClickListener listener) { return setNeutralButton(context().getText(resId), listener); } @Override public Builder setOnCancelListener(OnCancelListener onCancelListener) { this.onCancelListener = onCancelListener; return this; } @Override public Builder setPositiveButton(CharSequence text, OnClickListener listener) { buttonPositive = new ButtonEntry(text, listener); return this; } @Override public Builder setPositiveButton(int resId, OnClickListener listener) { return setPositiveButton(context().getText(resId), listener); } @Override public Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, OnClickListener listener) { return setSingleChoiceItems(new ArrayAdapter<CharSequence>( context(), android.R.layout.simple_list_item_single_choice, items), checkedItem, listener); } @Override public Builder setSingleChoiceItems(Cursor cursor, int checkedItem, String labelColumn, OnClickListener listener) { throw new RuntimeException( "setSingleChoiceItems with Cursor temporary not supported"); } @Override public Builder setSingleChoiceItems(int itemsId, int checkedItem, OnClickListener listener) { return setSingleChoiceItems(ArrayAdapter.createFromResource( context(), itemsId, android.R.layout.simple_list_item_single_choice), checkedItem, listener); } @Override public Builder setSingleChoiceItems(ListAdapter adapter, int checkedItem, OnClickListener listener) { return setItems(adapter, checkedItem, listener, AbsListView.CHOICE_MODE_SINGLE); } @Override public Builder setTitle(CharSequence title) { this.title = title; return this; } @Override public Builder setTitle(int titleId) { return setTitle(context().getText(titleId)); } public Builder setUseNative(boolean useNative) { this.useNative = useNative; return this; } public Builder setView(int resId) { return setView(resId, 0, 0, 0, 0); } public Builder setView(int resId, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom) { return setView(FontLoader.inflate(context(), resId), viewSpacingLeft, viewSpacingTop, viewSpacingRight, viewSpacingBottom); } @Override public Builder setView(View view) { setView(view, 0, 0, 0, 0); return this; } public Builder setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom) { this.view = view; setViewSpacingLeft(viewSpacingLeft); setViewSpacingTop(viewSpacingTop); setViewSpacingRight(viewSpacingRight); setViewSpacingBottom(viewSpacingBottom); return this; } public void setViewSpacingBottom(int viewSpacingBottom) { this.viewSpacingBottom = viewSpacingBottom; } public void setViewSpacingLeft(int viewSpacingLeft) { this.viewSpacingLeft = viewSpacingLeft; } public void setViewSpacingRight(int viewSpacingRight) { this.viewSpacingRight = viewSpacingRight; } public void setViewSpacingTop(int viewSpacingTop) { this.viewSpacingTop = viewSpacingTop; } } private static class ButtonEntry implements Entry<CharSequence, OnClickListener> { private OnClickListener listener; private CharSequence text; public ButtonEntry(CharSequence text, OnClickListener listener) { this.text = text; this.listener = listener; } @Override public CharSequence getKey() { return text; } @Override public OnClickListener getValue() { return listener; } @Override public OnClickListener setValue(OnClickListener object) { return listener = object; } } private static class InternalListener implements android.view.View.OnClickListener { private AlertDialog dialog; private OnClickListener listener; private int which; public InternalListener(final AlertDialog dialog, OnClickListener listener, int which) { this.dialog = dialog; this.listener = listener; this.which = which; } @Override public void onClick(View v) { if (listener != null) { listener.onClick(dialog, which); } try { dialog.dismiss(); dialog.cancel(); } catch (Exception e) { } } } private static int getDialogTheme(Context context) { TypedValue value = new TypedValue(); context.getTheme().resolveAttribute(R.attr.dialogStyle, value, true); return value.resourceId; } private static boolean useNative() { return VERSION.SDK_INT >= 14; } private ButtonEntry buttonNegative, buttonNeutral, buttonPositive; private DialogButtonBar buttonsLayout; private View customTitleView, lastCustomTitleView; private boolean dismissWhenOutside = true; private Drawable icon; private boolean oldTitleState = true; private CharSequence title; private boolean useNative; private View view; public AlertDialog(Context context) { this(context, useNative()); } public AlertDialog(Context context, boolean useNative) { this(context, getDialogTheme(context), useNative); } public AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) { this(context, cancelable, cancelListener, useNative()); } public AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener, boolean useNative) { super(context, getDialogTheme(context)); setCancelable(cancelable); setOnCancelListener(cancelListener); init(useNative); } public AlertDialog(Context context, int theme) { this(context, theme, useNative()); } public AlertDialog(Context context, int theme, boolean useNative) { super(context, theme); init(useNative); } private void checkTitleState() { checkTitleState(icon != null || title != null && title.length() > 0); } private void checkTitleState(boolean newState) { if (newState == oldTitleState) { return; } oldTitleState = newState; if (newState) { if (lastCustomTitleView != null) { setCustomTitle(lastCustomTitleView); } } else { setCustomTitle(null); } } public View getCustomTitle() { return customTitleView; } public Drawable getIcon() { return icon; } @Override public LayoutInflater getLayoutInflater() { return LayoutInflater.from(getContext()); } public CharSequence getTitle() { return title; } public View getView() { return view; } private void init(boolean useNative) { this.useNative = useNative; if (!useNative) { getWindow().setBackgroundDrawableResource(android.R.color.white); getWindow().setGravity(Gravity.CENTER); getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); getWindow().addFlags(LayoutParams.FLAG_DIM_BEHIND); TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.AlertDialog, android.R.attr.alertDialogStyle, R.style.Holo_AlertDialog); setDialogAlpha(a.getFloat(R.styleable.AlertDialog_dialogAlpha, 0.986f)); setDialogDimAmount(a.getFloat( R.styleable.AlertDialog_dialogDimAmount, 0.4f)); setDialogDismissWhenOutside(a.getBoolean( R.styleable.AlertDialog_dialogDismissWhenOutside, true)); a.recycle(); buttonsLayout = new DialogButtonBar(getContext()); setCustomTitle(R.layout.alert_dialog_title); } checkTitleState(false); } public boolean isUseNative() { return useNative; } @Override public boolean onTouchEvent(MotionEvent event) { if (dismissWhenOutside && (event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_OUTSIDE) { dismiss(); return false; } return super.onTouchEvent(event); } private void pushButton(ButtonEntry button, int which) { if (button == null || button.getKey() == null) { return; } Button b = new Button(getContext()); b.setText(button.getKey()); b.setOnClickListener(new InternalListener(this, button.getValue(), which)); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT); layoutParams.weight = 1; buttonsLayout.addView(b, layoutParams); } @Override public void setButton(int whichButton, CharSequence text, OnClickListener listener) { if (useNative) { super.setButton(whichButton, text, listener); } else { ButtonEntry entry = new ButtonEntry(text, listener); switch (whichButton) { case BUTTON_NEGATIVE: buttonNegative = entry; break; case BUTTON_POSITIVE: buttonPositive = entry; break; case BUTTON_NEUTRAL: buttonNeutral = entry; break; } updateButtonsLayout(); } } public void setCustomTitle(int resID) { setCustomTitle(FontLoader.inflate(getContext(), resID)); } @Override public void setCustomTitle(View customTitleView) { lastCustomTitleView = this.customTitleView; super.setCustomTitle(this.customTitleView = customTitleView); } public void setDialogAlpha(float alpha) { getWindow().getAttributes().alpha = alpha; } public void setDialogDimAmount(float dimAmount) { getWindow().getAttributes().dimAmount = dimAmount; } public void setDialogDismissWhenOutside(boolean dismissWhenOutside) { this.dismissWhenOutside = dismissWhenOutside; if (dismissWhenOutside) { getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); getWindow().addFlags(LayoutParams.FLAG_NOT_TOUCH_MODAL); } else { getWindow().clearFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); getWindow().clearFlags(LayoutParams.FLAG_NOT_TOUCH_MODAL); } } @Override public void setIcon(Drawable icon) { this.icon = icon; if (useNative) { super.setIcon(icon); } else { checkTitleState(); if (getCustomTitle() != null) { ImageView image = (ImageView) getCustomTitle().findViewById( R.id.icon); if (image != null) { image.setImageDrawable(icon); } } } } @Override public void setIcon(int resId) { setIcon(getContext().getResources().getDrawable(resId)); } @Override public void setMessage(CharSequence message) { if (useNative) { super.setMessage(message); } else { View customMessage = FontLoader.inflate(getContext(), R.layout.alert_dialog_message); TextView messageView = (TextView) customMessage .findViewById(R.id.message); messageView.setText(message); setView(customMessage); } } public void setMessage(int res) { setMessage(getContext().getText(res)); } @Override public void setTitle(CharSequence title) { this.title = title; if (useNative) { super.setTitle(title); } else { checkTitleState(); if (getCustomTitle() != null) { TextView view = (TextView) getCustomTitle().findViewById( R.id.alertTitle); if (view != null) { view.setText(title); } } } } @Override public void setTitle(int res) { setTitle(getContext().getText(res)); } public void setView(int resId) { setView(resId, 0, 0, 0, 0); } public void setView(int resId, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom) { setView(View.inflate(getContext(), resId, null), viewSpacingLeft, viewSpacingTop, viewSpacingRight, viewSpacingBottom); } @Override public void setView(View view) { setView(view, 0, 0, 0, 0); } @Override public void setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, int viewSpacingBottom) { this.view = view; if (view == null) { return; } FontLoader.loadFont(view); if (useNative) { super.setView(view, viewSpacingLeft, viewSpacingTop, viewSpacingRight, viewSpacingBottom); } else { LinearLayout layout = new LinearLayout(getContext()); layout.setBackgroundResource(android.R.color.white); layout.setOrientation(LinearLayout.VERTICAL); layout.addView(view); try { ((LinearLayout) buttonsLayout.getParent()) .removeView(buttonsLayout); } catch (Exception e) { } LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.setMargins(0, viewSpacingBottom, 0, 0); layout.addView(buttonsLayout, params); super.setView(layout, viewSpacingLeft, viewSpacingTop, viewSpacingRight, 0); } } private void updateButtonsLayout() { buttonsLayout.removeAllViews(); pushButton(buttonNegative, DialogInterface.BUTTON_NEGATIVE); pushButton(buttonNeutral, DialogInterface.BUTTON_NEUTRAL); pushButton(buttonPositive, DialogInterface.BUTTON_POSITIVE); buttonsLayout.rebuild(); FontLoader.loadFont(buttonsLayout); } }