建造者模式打造隨心所欲的Android對話方塊
可能有人要說不就是自定義dialog嗎,網上一搜案例demo多得是,而且也不難,沒什麼好講的。確實百度一下自定義的dialog數不勝數。但是大多數文章都是單一的佈局實現單一的樣式。假如說專案中有多個不同佈局的dialog,比如三種、五種甚至十種,當然我只說假如。如果你的專案只有一種樣式的對話方塊。那麼也沒有必要再看再往下看了。
如上所述,碰到多種樣式的對話方塊應該怎麼辦呢?總不能專案需要幾種就去寫幾種自定義樣式吧?很顯然我們不會那樣做!所以這就是寫這篇文章的用意。接下來我們將通過建造者模式來自定義dialog,並對自定義的dialog做下簡單封裝,最後實現的需求是隻需要寫dialog的佈局檔案即可實現任意樣式的對話方塊!有木有很心動?閒話不多扯了,開擼!
國際慣例,開擼前先看效果圖。圖中使用同一個自定義dialog實現了兩種不同樣式的對話方塊。
一、用建造者模式實現自定義Dialog
1.首先我們要做的是去自定義Dialog,建立CustomDialog並繼承Dialog。
2.明確Dialog所需要的屬性,寬度、高度、Dialog的佈局所對應的View、點選外部是否取消dialog、以及Dialog的主題(Theme),其中主題(Theme)我們沒有定義在CustomDialog內部,而是定義到了Builder中。因此需要在CustomDialog內定義如下成員變數:
// dialog高度
private int height;
// dialog寬度
private int width;
// 點選外部是否可以取消
private boolean cancelTouchOutside;
// 對話方塊佈局對應的View
private View dialogView;
3.接下來我們在CustomDialog內部建立靜態內部類Builder,根據Dialog佈局計算dialog寬高,並給定預設的對話方塊佈局樣式custom_dialog2。如下圖(頁面佈局程式碼不再貼出):
Builder程式碼如下:
public static final class Builder {
private Context context;
private int height, width;
private boolean cancelTouchOutside;
private View mDialogView;
private int resStyle = -1;
public Builder(Context context) {
this.context = context;
mDialogView = LayoutInflater.from(context).inflate(R.layout.custom_dialog2, null);
// 計算dialog寬高
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
mDialogView.measure(measureSpec, measureSpec);
height = mDialogView.getMeasuredHeight();
width = mDialogView.getMeasuredWidth();
}
/**
* @param dialogView 關聯dialog佈局檔案的View
* @return
*/
public Builder setDialogLayout(View dialogView) {
this.mDialogView = dialogView;
return this;
}
public Builder setHeightPx(int val) {
height = val;
return this;
}
public Builder setWidthPx(int val) {
width = val;
return this;
}
public Builder setHeightDp(int val) {
height = ScreenUtils.dp2px(context, val);
return this;
}
public Builder setWidthDp(int val) {
width = ScreenUtils.dp2px(context, val);
return this;
}
/**
* 設定主題
*
* @param resStyle
* @return
*/
public Builder setTheme(int resStyle) {
this.resStyle = resStyle;
return this;
}
/**
* 設定點選dialog外部是否取消dialog
*
* @param val
* @return
*/
public Builder cancelTouchOutside(boolean val) {
cancelTouchOutside = val;
return this;
}
/**
* 給dialog中的view新增點選事件
*
* @param viewResId 被點選view的id
* @param listener
* @return
*/
public Builder addViewOnclick(int viewResId, View.OnClickListener listener) {
mDialogView.findViewById(viewResId).setOnClickListener(listener);
return this;
}
/**
* 確定鍵監聽
* @param confirm
* @param listener
* @return
*/
public Builder addConfirmClickListener(String confirm, View.OnClickListener listener) {
TextView tvConfirm = (TextView) mDialogView.findViewById(R.id.tv_confirm);
tvConfirm.setText(confirm);
tvConfirm.setOnClickListener(listener);
return this;
}
/**
* 取消鍵監聽
* @param cancel
* @param listener
* @return
*/
public Builder addCancelClickListener(String cancel, View.OnClickListener listener) {
TextView tvCancel = (TextView) mDialogView.findViewById(R.id.tv_cancel);
tvCancel.setText(cancel);
tvCancel.setOnClickListener(listener);
return this;
}
/**
* 設定內容
* @param content
* @return
*/
public Builder setContent(String content) {
TextView tvTitle = (TextView) mDialogView.findViewById(R.id.tv_dialog_content);
tvTitle.setText(content);
return this;
}
/**
* 設定取消鍵顏色
* @param color 顏色
* @return
*/
public Builder setCancelColor(int color){
TextView tvCancel= (TextView) mDialogView.findViewById(R.id.tv_cancel);
tvCancel.setTextColor(color);
return this;
}
/**
* 設定確定鍵顏色
* @param color 顏色
* @return
*/
public Builder setConfirmColor(int color){
TextView tvCancel= (TextView) mDialogView.findViewById(R.id.tv_confirm);
tvCancel.setTextColor(color);
return this;
}
/**
* 顯示一個按鈕的彈窗
* @return
*/
public Builder showOneButton() {
mDialogView.findViewById(R.id.tv_cancel).setVisibility(View.GONE);
mDialogView.findViewById(R.id.view_dialog).setVisibility(View.GONE);
return this;
}
public CustomDialog build() {
if (resStyle != -1) {
return new CustomDialog(this, resStyle);
} else {
return new CustomDialog(this);
}
}
}
5.上面程式碼在build()方法中例項化了CustomDialog,因此我們不要忘了CustomDialog中的構造方法。在構造方法中獲取Builder中的屬性。構造方法有兩個,如下:
private CustomDialog(Builder builder) {
super(builder.context);
height = builder.height;
width = builder.width;
cancelTouchOutside = builder.cancelTouchOutside;
dialogView = builder.mDialogView;
}
private CustomDialog(Builder builder, int theme) {
super(builder.context, theme);
height = builder.height;
width = builder.width;
cancelTouchOutside = builder.cancelTouchOutside;
dialogView = builder.mDialogView;
}
6.最後還要在onCreate()中為dialog設定佈局和一些其他屬性。程式碼如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(dialogView);
// 設定Touch的時候是否取消Dialog
setCanceledOnTouchOutside(cancelTouchOutside);
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.gravity = Gravity.CENTER;
params.height = height;
params.width = width;
window.setAttributes(params);
}
這樣自定義的Dialog就完成了。
二、對自定義的dialog簡單封裝。
完成自定義dialog之後接下來我們在專案的BaseActivity中對自定義的dialog做下封裝。由於在構建DIalog的建造者時已經事先給定了預設佈局,因此先對預設佈局做下封裝。
1.在BaseActivity中封裝只有一個Button的對話方塊,並指定半透明背景樣式,程式碼如下:
/**
* @param content 內容
* @param confirm 按鈕文字
* @param confirmListener 按鈕監聽
*/
public void showOneButtonDialog(String content, String confirm, View.OnClickListener confirmListener) {
dialog = new CustomDialog.Builder(this)
.setTheme(R.style.CustomDialog1)
.setContent(content)
.addConfirmClickListener(confirm, confirmListener)
.showOneButton()
.build();
dialog.show();
}
2.封裝兩個按鈕的dialog,指定半透明背景。程式碼如下:
/**
* @param content 內容
* @param confirm 確定鍵文字
* @param cancel 取消鍵文字
* @param confirmListener 確定鍵監聽
* @param cancelListener 取消鍵監聽
*/
public void showTwoButtonDialog(String content, String confirm, String cancel,
View.OnClickListener confirmListener,
View.OnClickListener cancelListener) {
dialog = new CustomDialog.Builder(this)
.setTheme(R.style.CustomDialog1)
.setContent(content)
.addConfirmClickListener(confirm, confirmListener)
.addCancelClickListener(cancel, cancelListener)
.build();
dialog.show();
}
3.封裝兩個按鈕切能改變按鈕字型顏色的對話方塊,背景指定全透明,程式碼如下:
/**
* @param content 內容
* @param confirm 確定鍵文字
* @param cancel 取消鍵文字
* @param confirmColor 確定鍵顏色
* @param cancelColor 取消鍵顏色
* @param confirmListener 確定鍵監聽
* @param cancelListener 取消鍵監聽
*/
public void showTwoButtonDialog(String content, String confirm, String cancel,
@ColorInt int confirmColor, @ColorInt int cancelColor,
View.OnClickListener confirmListener,
View.OnClickListener cancelListener) {
dialog = new CustomDialog.Builder(this)
.setTheme(R.style.CustomDialog2)
.setContent(content)
.setConfirmColor(confirmColor)
.setCancelColor(cancelColor)
.addConfirmClickListener(confirm, confirmListener)
.addCancelClickListener(cancel, cancelListener)
.build();
dialog.show();
}
4.封裝自定義樣式的對話方塊,需要自行定義對話方塊佈局檔案。程式碼如下:
/**
* create custom dialog
* 可以定製任意的dialog樣式
*
* @param dialogLayoutRes dialog佈局資原始檔
* @param cancelTouchOutside 點選外部是否可以取消
* @return
*/
public View createCustomDialog(@LayoutRes int dialogLayoutRes, boolean cancelTouchOutside) {
dialogView = LayoutInflater.from(this).inflate(dialogLayoutRes, null);
// 計算dialog寬高
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
dialogView.measure(measureSpec, measureSpec);
int height = dialogView.getMeasuredHeight();
int width = dialogView.getMeasuredWidth();
dialog = new CustomDialog.Builder(this)
.setTheme(R.style.CustomDialog1)
.setHeightPx(height)
.setWidthPx(width)
.cancelTouchOutside(cancelTouchOutside)
.setDialogLayout(dialogView).build();
dialog.show();
return dialogView;
}
自定義樣式的dialog由於沒有給定點選事件,因此需要在Activity中新增dismiss dialog的方法,可以在子Activity中自定義點選事件的時候呼叫,如下:
/**
* 隱藏dialog
*/
public void dismissDialog() {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
三、在子Activity中根據需求顯示不同的對話方塊。
MainActivity繼承BaseActivity,並在MainActivity中呼叫BaseActivity中的不同對話方塊的方法顯示對話方塊。程式碼如下:
// 顯示一個按鈕的對話方塊
private void showOneButton(){
showOneButtonDialog("一個Button的Dialog", "確定", new View.OnClickListener() {
@Override
public void onClick(View v) {
dismissDialog();
}
});
}
// 顯示兩個按鈕的對話方塊
private void showTwoButton(){
showTwoButtonDialog("兩個Button的Dialog", "確定", "取消",
new View.OnClickListener() {
@Override
public void onClick(View v) {
dismissDialog();
}
}, new View.OnClickListener() {
@Override
public void onClick(View v) {
dismissDialog();
}
});
}
// 顯示兩個按鈕且可以改變按鈕顏色且背景全透明的對話方塊
public void showTowButtonWithColor() {
showTwoButtonDialog("改變Button顏色的Dialog\n背景全透明", "確定", "取消",
Color.parseColor("#ff0000"), Color.parseColor("#00ff00"),
new View.OnClickListener() {
@Override
public void onClick(View v) {
dismissDialog();
}
}, new View.OnClickListener() {
@Override
public void onClick(View v) {
dismissDialog();
}
});
}
// 顯示自定義樣式的對話方塊
private void showCustomDialog() {
mDialogView1 = createCustomDialog(R.layout.custom_dialog1, false);
// 為自定義的dialog設定內容、新增點選事件
TextView viewById1 = (TextView) mDialogView1.findViewById(R.id.tv_dialog_content);
viewById1.setText("自定義樣式的Dialog");
mDialogView1.findViewById(R.id.btn_dialog).setOnClickListener(this);
}
上面程式碼自定義對話方塊createCustomDialog()方法的返回值是自定義佈局檔案對應的View,因此可以通過該View獲取到佈局中的所有子View,然後為其設定內容或者監聽事件。
相關文章
- 讓 sudo 會話時間隨心所欲會話
- 可以隨心所欲的canvas粒子特效Canvas特效
- React中的模式對話方塊React模式
- 一段對話講完建造者模式模式
- android 多項對話方塊Android
- Android Dialog對話方塊Android
- Permute 3 Mac:格式轉換,隨心所欲Mac
- android常用對話方塊封裝Android封裝
- Android對話方塊Dialog深度剖析Android
- Android 對話方塊 Dialog 深度剖析Android
- Android通知之普通對話方塊通知Android
- Android通知之列表對話方塊通知Android
- Android通知之多選對話方塊通知Android
- 編輯Android程式遊戲對話方塊Android遊戲
- Android UI系列-----Dialog對話方塊AndroidUI
- Ableton Live 11 Suite:無限創造,隨心所欲UI
- c#中的模態對話方塊和非模態對話方塊C#
- Android通知之單選對話方塊通知Android
- 對話方塊函式函式
- 登入對話方塊
- PHP指令碼:隨心所欲的程式碼逐漸流行(轉)PHP指令碼
- Android通知之進度條對話方塊通知Android
- Android自定義View(1):對話方塊-DialogAndroidView
- Android 官方推薦 : DialogFragment 建立對話方塊AndroidFragment
- [MFC]選擇目錄對話方塊和選擇檔案對話方塊
- flutter demo (四):對話方塊Flutter
- Javascript檔案對話方塊JavaScript
- Android——最全的系統對話方塊(AlertDialog)詳解Android
- VUE:點選開啟的對話方塊外面時,對話方塊總是被關閉Vue
- GNU EMACS字型設定,基本上可以隨心所欲(轉)Mac
- IE中非模式對話方塊(showModelessDialog)應用 (轉)模式
- 一個Flex 對話方塊的坑Flex
- javascript中的彈出對話方塊JavaScript
- 建造者模式模式
- Android UI控制元件系列:Dialog(對話方塊)AndroidUI控制元件
- android漂亮的對話方塊專案sweet-alert-dialogAndroid
- 在 Flutter 使用 GetX 對話方塊Flutter
- Qt 對話方塊新增工具欄QT