Create custom dialogs
Don’t like android system dialog style? You want to change it. However, the commonly used AlertDialog doesn’t allow you change the title bar, change the background, change the button style… We need to inherit Dialog class to make everything by ourselves.
Common alert dialog:
public class CommonDialog extends Dialog {
// UI
private TextView mTitleTextView;
private ImageView mTitleIcon;
private Button mButton1;
private Button mButton2;
private Button mButton3;
private View mButtonBar;
private View mLeftSpacer;
private View mRightSpacer;
private LinearLayout mContentViewContainer;
private View mCustomContentView;
private TextView mMessageTextView;
// Data
private CharSequence mTitleText;
private CharSequence mDialogMessage;
private int mTitleIconResource;
private CharSequence mButton1Text;
private CharSequence mButton2Text;
private CharSequence mButton3Text;
private DialogInterface.OnClickListener mButton1OnClickListner;
private DialogInterface.OnClickListener mButton2OnClickListner;
private DialogInterface.OnClickListener mButton3OnClickListner;
// Flag to decide if the dialog has been displayed.
private boolean mHasDisplayed;
private View.OnClickListener mOnButtonClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean bottomBtnClicked = false;
int which = 0;
switch (v.getId()) {
case R.id.btn_common_dlg_button1:
bottomBtnClicked = true;
which = DialogInterface.BUTTON_POSITIVE;
break;
case R.id.btn_common_dlg_button2:
bottomBtnClicked = true;
which = DialogInterface.BUTTON_NEGATIVE;
break;
case R.id.btn_common_dlg_button3:
bottomBtnClicked = true;
which = DialogInterface.BUTTON_NEUTRAL;
break;
}
if (bottomBtnClicked) {
if (mButton1OnClickListner != null && which == DialogInterface.BUTTON_POSITIVE) {
mButton1OnClickListner.onClick(CommonDialog.this, which);
}
if (mButton2OnClickListner != null && which == DialogInterface.BUTTON_NEGATIVE) {
mButton2OnClickListner.onClick(CommonDialog.this, which);
}
if (mButton3OnClickListner != null && which == DialogInterface.BUTTON_NEUTRAL) {
mButton3OnClickListner.onClick(CommonDialog.this, which);
}
}
}
};
public CommonDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
}
public CommonDialog(Context context, int theme) {
super(context, theme);
}
public CommonDialog(Context context) {
super(context, R.style.CustomDialog);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.common_dialog);
// Title bar
mTitleTextView = (TextView)findViewById(R.id.tv_common_dlg_title);
if (!TextUtils.isEmpty(mTitleText)) {
mTitleTextView.setText(mTitleText);
}
mTitleIcon = (ImageView)findViewById(R.id.iv_common_dlg_title_icon);
if (mTitleIconResource > 0) {
mTitleIcon.setImageResource(mTitleIconResource);
}
// Buttons
mButton1 = (Button)findViewById(R.id.btn_common_dlg_button1);
if (!TextUtils.isEmpty(mButton1Text)) {
mButton1.setText(mButton1Text);
}
mButton1.setOnClickListener(mOnButtonClickListener);
mButton2 = (Button)findViewById(R.id.btn_common_dlg_button2);
if (!TextUtils.isEmpty(mButton2Text)) {
mButton2.setText(mButton2Text);
}
mButton2.setOnClickListener(mOnButtonClickListener);
mButton3 = (Button)findViewById(R.id.btn_common_dlg_button3);
if (!TextUtils.isEmpty(mButton3Text)) {
mButton3.setText(mButton3Text);
}
mButton3.setOnClickListener(mOnButtonClickListener);
mLeftSpacer = findViewById(R.id.ll_common_dlg_left_spacer);
mRightSpacer = findViewById(R.id.ll_common_dlg_right_spacer);
// Button bar
mButtonBar = findViewById(R.id.ll_common_dlg_button_bar);
// Content
mContentViewContainer = (LinearLayout)findViewById(R.id.ll_common_dlg_content);
if (mCustomContentView != null) {
mContentViewContainer.addView(mCustomContentView);
}
// Text view
mMessageTextView = (TextView)mContentViewContainer
.findViewById(R.id.tv_common_dialog_message);
if(!TextUtils.isEmpty(mDialogMessage)){
mMessageTextView.setText(mDialogMessage);
}
mHasDisplayed = true;
updateViews();
}
/**
* Add your custom view into the dialog.
*
* @param contentView your custom view
*/
public void insertContentView(View contentView) {
mCustomContentView = contentView;
if (mContentViewContainer != null) {
mContentViewContainer.removeAllViews();
LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
mContentViewContainer.addView(contentView, layoutParams);
}
}
private void updateViews() {
if (mHasDisplayed) {
boolean hasButton = updateButtons();
if (hasButton) {
mContentViewContainer.setBackgroundResource(R.drawable.bg_dialog_content);
mButtonBar.setVisibility(View.VISIBLE);
} else {
mContentViewContainer.setBackgroundResource(R.drawable.bg_dialog_bottom_bar_no_button);
mButtonBar.setVisibility(View.GONE);
}
}
}
private boolean updateButtons() {
int BIT_BUTTON_1 = 1;
int BIT_BUTTON_2 = 2;
int BIT_BUTTON_3 = 4;
int whichButtons = 0;
if (TextUtils.isEmpty(mButton1.getText())) {
mButton1.setVisibility(View.GONE);
mButton1.setOnClickListener(null);
} else {
mButton1.setVisibility(View.VISIBLE);
whichButtons = whichButtons | BIT_BUTTON_1;
}
if (TextUtils.isEmpty(mButton2.getText())) {
mButton2.setVisibility(View.GONE);
mButton2.setOnClickListener(null);
} else {
mButton2.setVisibility(View.VISIBLE);
whichButtons = whichButtons | BIT_BUTTON_2;
}
if (TextUtils.isEmpty(mButton3.getText())) {
mButton3.setVisibility(View.GONE);
mButton3.setOnClickListener(null);
} else {
mButton3.setVisibility(View.VISIBLE);
whichButtons = whichButtons | BIT_BUTTON_3;
}
if (whichButtons == BIT_BUTTON_1) {
centerButton(mButton1);
} else if (whichButtons == BIT_BUTTON_2) {
centerButton(mButton2);
} else if (whichButtons == BIT_BUTTON_3) {
centerButton(mButton3);
} else {
mLeftSpacer.setVisibility(View.GONE);
mRightSpacer.setVisibility(View.GONE);
}
return whichButtons != 0;
}
/**
* Set title text.
*/
@Override
public void setTitle(CharSequence title) {
mTitleText = title;
if (mTitleTextView != null) {
mTitleTextView.setText(title);
}
}
/**
* Set title text.
*/
public void setTitleIconResource(int titleIconRes) {
mTitleIconResource = titleIconRes;
if (mTitleIcon != null) {
mTitleIcon.setImageResource(titleIconRes);
}
}
/**
* Set left button.
*/
public void setPositiveButton(CharSequence text, DialogInterface.OnClickListener onClickListener) {
mButton1Text = text;
mButton1OnClickListner = onClickListener;
if (mButton1 != null) {
mButton1.setText(text);
mButton1.setOnClickListener(mOnButtonClickListener);
}
}
/**
* Set left button.
*/
public void setPositiveButton(int textRes, DialogInterface.OnClickListener onClickListener) {
setPositiveButton(getContext().getText(textRes), onClickListener);
}
/**
* Set right button.
*/
public void setNegativeButton(CharSequence text, DialogInterface.OnClickListener onClickListener) {
mButton2Text = text;
mButton2OnClickListner = onClickListener;
if (mButton2 != null) {
mButton2.setText(text);
mButton2.setOnClickListener(mOnButtonClickListener);
}
}
/**
* Set right button.
*/
public void setNegativeButton(int textRes, DialogInterface.OnClickListener onClickListener) {
setNegativeButton(getContext().getText(textRes), onClickListener);
}
/**
* Set middle button.
*/
public void setNeutralButton(CharSequence text, DialogInterface.OnClickListener onClickListener) {
mButton3Text = text;
mButton3OnClickListner = onClickListener;
if (mButton3 != null) {
mButton3.setText(text);
mButton3.setOnClickListener(mOnButtonClickListener);
}
}
/**
* Set middle button.
*/
public void setNeutralButton(int textRes, DialogInterface.OnClickListener onClickListener) {
setNeutralButton(getContext().getText(textRes), onClickListener);
}
private void centerButton(Button button) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)button.getLayoutParams();
params.gravity = Gravity.CENTER_HORIZONTAL;
params.weight = 0.5f;
button.setLayoutParams(params);
mLeftSpacer.setVisibility(View.VISIBLE);
mRightSpacer.setVisibility(View.VISIBLE);
}
/**
* Create alert dialog with OK button.
*/
public static CommonDialog createAlertMessageDialog(Context context,
CharSequence titleText, CharSequence messageText) {
CommonDialog dlg = new CommonDialog(context);
setupCommonMessageDialog(context, titleText, messageText, dlg);
dlg.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
return dlg;
}
protected static void setupCommonMessageDialog(Context context, CharSequence titleText,
CharSequence messageText, final CommonDialog dialog) {
dialog.setTitle(titleText);
LayoutInflater inflater = (LayoutInflater)context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View messageView = inflater.inflate(R.layout.common_dialog_message_view, null);
TextView msgTextView = (TextView)messageView
.findViewById(R.id.tv_common_dialog_message);
msgTextView.setText(messageText);
dialog.insertContentView(messageView);
}
/**
* Create alert dialog with OK button.
*/
public static CommonDialog createAlertMessageDialog(Context context, int titleTextRes,
int messageTextRes) {
return createAlertMessageDialog(context, context.getString(titleTextRes), context
.getString(messageTextRes));
}
/**
* Create confirm dialog with OK and CANCEL button.
*/
public static CommonDialog createConfirmDialog(Context context, CharSequence titleText,
CharSequence messageText) {
final CommonDialog dialog = new CommonDialog(context);
setupCommonMessageDialog(context, titleText, messageText, dialog);
dialog.setPositiveButton(R.string.ok, null);
dialog.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
return dialog;
}
/**
* Create confirm dialog with OK and CANCEL button.
*/
public static CommonDialog createConfirmDialog(Context context, int titleTextRes,
int messageTextRes) {
return createConfirmDialog(context, context.getString(titleTextRes), context
.getString(messageTextRes));
}
public void setDialogMessage(int messageTextRes){
setDialogMessage(getContext().getString(messageTextRes));
}
/**
* Update the dialog message.
*
* Only for simple alert dialog and confirm dialog.
* You must call createAlertMessage or createConfirmDialog first.
*
* @param messageText
*/
public void setDialogMessage(CharSequence messageText) {
mDialogMessage = messageText;
if (mMessageTextView != null) {
mMessageTextView.setText(messageText);
}
}
}
Let’s custom our dialog view:
And here’s the custom linear layout:
public class WeightedLinearLayout extends LinearLayout {
private static final float DEFAULT_PORTRAIT_WIDTH_WEIGHT = 0.9f;
private static final float DEFAULT_LANDSCAPE_WIDTH_WEIGHT = 0.9f;
private static final float DEFAULT_PORTRAIT_HEIGHT_MIN_WEIGHT = 0.375f;
private static final float DEFAULT_PORTRAIT_HEIGHT_MAX_WEIGHT = 0.725f;
private static final float DEFAULT_LANDSCAPE_HEIGHT_MIN_WEIGHT = 0.375f;
private static final float DEFAULT_LANDSCAPE_HEIGHT_MAX_WEIGHT = 0.725f;
private float mPortraitWidthWeight;
private float mLandscapeWidthWeight;
private float mPortraitHeightMinWeight;
private float mPortraitHeightMaxWeight;
private float mLandscapeHeightMinWeight;
private float mLandscapeHeightMaxWeight;
public WeightedLinearLayout(Context context) {
super(context);
}
public WeightedLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WeightedLinearLayout);
mPortraitWidthWeight = a.getFloat(R.styleable.WeightedLinearLayout_portraitWidthWeight, DEFAULT_PORTRAIT_WIDTH_WEIGHT);
mLandscapeWidthWeight = a.getFloat(R.styleable.WeightedLinearLayout_landscapeWidthWeight, DEFAULT_LANDSCAPE_WIDTH_WEIGHT);
mPortraitHeightMinWeight = a.getFloat(R.styleable.WeightedLinearLayout_portraitHeightMinWeight, DEFAULT_PORTRAIT_HEIGHT_MIN_WEIGHT);
mPortraitHeightMaxWeight = a.getFloat(R.styleable.WeightedLinearLayout_portraitHeightMaxWeight, DEFAULT_PORTRAIT_HEIGHT_MAX_WEIGHT);
mLandscapeHeightMinWeight = a.getFloat(R.styleable.WeightedLinearLayout_landscapeHeightMinWeight, DEFAULT_LANDSCAPE_HEIGHT_MIN_WEIGHT);
mLandscapeHeightMaxWeight = a.getFloat(R.styleable.WeightedLinearLayout_landscapeHeightMaxWeight, DEFAULT_LANDSCAPE_HEIGHT_MAX_WEIGHT);
a.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
int screenWidth = metrics.widthPixels;
int screenHeight = metrics.heightPixels;
boolean isPortrait = screenWidth < screenHeight;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
boolean measure = false;
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
float widthWeight = isPortrait ? mPortraitWidthWeight : mLandscapeWidthWeight;
if (widthMode == MeasureSpec.AT_MOST && widthWeight > 0.0f) {
//if (width < (screenWidth * widthWeight)) {
widthMeasureSpec = MeasureSpec.makeMeasureSpec((int)(screenWidth * widthWeight),
MeasureSpec.EXACTLY);
measure = true;
//}
}
float minHeight = isPortrait ? mPortraitHeightMinWeight : mLandscapeHeightMinWeight;
float maxHeight = isPortrait ? mPortraitHeightMaxWeight : mLandscapeHeightMaxWeight;
if(heightMode == MeasureSpec.AT_MOST) {
if(minHeight > 0.0f && height < (screenHeight * minHeight)){
heightMeasureSpec = MeasureSpec.makeMeasureSpec((int)(screenHeight * minHeight),
MeasureSpec.EXACTLY);
measure = true;
} else if(maxHeight > 0.0f && height > (screenHeight * maxHeight)){
heightMeasureSpec = MeasureSpec.makeMeasureSpec((int)(screenHeight * maxHeight),
MeasureSpec.EXACTLY);
measure = true;
}
}
if (measure) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void setPortraitHeightMinWeight(float portraitHeightMinWeight) {
this.mPortraitHeightMinWeight = portraitHeightMinWeight;
}
public void setLandscapeHeightMinWeight(float landscapeHeightMinWeight) {
this.mLandscapeHeightMinWeight = landscapeHeightMinWeight;
}
}
Now, let’s do some extension, create input dialog based on the common dialog:
public class CommonInputDialog extends CommonDialog {
protected EditText mEditText;
public CommonInputDialog(Context context) {
super(context);
initEditTextView();
}
private void initEditTextView() {
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
LinearLayout editContainer = (LinearLayout)inflater.inflate(R.layout.common_dialog_edit_text, null);
editContainer.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
mEditText = (EditText) editContainer.findViewById(R.id.et_common_dialog);
insertContentView(editContainer);
}
public String getInputText(){
return mEditText.getText().toString();
}
public void setInputText(String text) {
mEditText.setText(text);
}
public EditText getEditTextView() {
return mEditText;
}
public void setError(String errText, Drawable indicatorError) {
mEditText.setError(errText, indicatorError);
}
public static CommonInputDialog createSimpleInputDialog(Context context, String title){
CommonInputDialog inputDialog = new CommonInputDialog(context);
inputDialog.setTitle(title);
inputDialog.setPositiveButton(R.string.ok, null);
inputDialog.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
return inputDialog;
}
public static CommonInputDialog createSimpleInputDialog(Context context, int titleRes){
return createSimpleInputDialog(context, context.getString(titleRes));
}
}
And a simple list dialog:
public class CommonListDialog extends CommonDialog {
protected ListView mListView;
protected TextView mEmptyListTextView;
protected String mEmptyListText;
public CommonListDialog(Context context) {
super(context);
initListView();
FrameLayout listViewContainer = new FrameLayout(getContext());
listViewContainer.setLayoutParams(new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT));
listViewContainer.addView(mListView, new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT));
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View emptyViewContainer = inflater.inflate(R.layout.common_dialog_message_view, null);
mEmptyListTextView = (TextView)emptyViewContainer.findViewById(R.id.tv_common_dialog_message);
listViewContainer.addView(emptyViewContainer, new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT));
mListView.setEmptyView(emptyViewContainer);
insertContentView(listViewContainer);
}
public void setEmptyListText(String emptyText) {
mEmptyListText = emptyText;
if (mEmptyListTextView != null && !TextUtils.isEmpty(mEmptyListText)) {
mEmptyListTextView.setText(mEmptyListText);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (mEmptyListTextView != null && !TextUtils.isEmpty(mEmptyListText)) {
mEmptyListTextView.setText(mEmptyListText);
}
if (mListView.getCount() > 0) {
WeightedLinearLayout dlgContainer = (WeightedLinearLayout)findViewById(R.id.ll_common_dlg_container);
dlgContainer.setPortraitHeightMinWeight(0);
dlgContainer.setLandscapeHeightMinWeight(0);
}
}
protected void initListView() {
mListView = new ListView(getContext());
LayoutParams layoutParams = new ListView.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
mListView.setLayoutParams(layoutParams);
mListView.setCacheColorHint(0);
mListView.setDividerHeight(1);
}
/**
* Set adapter to the list.
*
* @param adapter
*/
public void setListAdapter(ListAdapter adapter) {
if (mListView != null) {
mListView.setAdapter(adapter);
}
}
/**
* Set listener for click on the list view.
*
* @param onItemClickListener
*/
public void setOnListItemClickListener(OnItemClickListener onItemClickListener) {
if (mListView != null) {
mListView.setOnItemClickListener(onItemClickListener);
}
}
public ListView getListView() {
return mListView;
}
/**
* Create a simple list dialog.
*
* @param context
* @param title
* @param listEntries
* @return
*/
public static CommonListDialog createSimpleListDialog(Context context, String title,
String[] listEntries) {
CommonListDialog listDialog = new CommonListDialog(context);
listDialog.setTitle(title);
ArrayAdapter adapter = new ArrayAdapter(context,
R.layout.simple_dialog_listview_item, R.id.tv_list_text, listEntries);
listDialog.setListAdapter(adapter);
return listDialog;
}
/**
* Create a simple list dialog.
*
* @param context
* @param titleRes
* @param listEntries
* @return
*/
public static CommonListDialog createSimpleListDialog(Context context, int titleRes,
String[] listEntries) {
return createSimpleListDialog(context, context.getString(titleRes), listEntries);
}
/**
* Create a simple list dialog with header.
*
* @param context
* @param title
* @param listEntries
* @param headerText
* @return
*/
public static CommonListDialog createSimpleListDialogWithHeader(Context context,
String title, String[] listEntries, String headerText) {
CommonListDialog listDialog = new CommonListDialog(context);
ListView listView = listDialog.getListView();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View headerView = inflater.inflate(R.layout.list_header_in_dialog, null);
TextView textView = (TextView)headerView.findViewById(R.id.tv_list_header_in_dialog);
textView.setText(headerText);
listView.addHeaderView(headerView);
listDialog.setTitle(title);
ArrayAdapter adapter = new ArrayAdapter(context,
R.layout.simple_dialog_listview_item, R.id.tv_list_text, listEntries);
listDialog.setListAdapter(adapter);
return listDialog;
}
/**
* Create a simple list dialog with header.
*
* @param context
* @param titleRes
* @param listEntries
* @param headerTextRes
* @return
*/
public static CommonListDialog createSimpleListDialogWithHeader(Context context, int titleRes,
String[] listEntries, int headerTextRes) {
return createSimpleListDialogWithHeader(context, context.getString(titleRes),
listEntries, context.getString(headerTextRes));
}
}
And now, you can create other dialogs easily!
