前言
在Android開發中我們常常需要使用Dialog來處理一些彈窗操作。雖然Android系統本身為我們封裝了一個自帶的彈窗Dialog,但是由於Android作業系統的不同,導致了每個手機彈窗頁面的不同,以至於我們很難用系統的去統一樣式。並且UI會覺得系統的彈窗過於醜陋,希望自己來做一個於是我們便需要自己來處理一個Dialog彈窗。今天叫大家利用Builder構造者模式自己來封裝一個彈窗Dialog。
需求分析
首先確定一下,彈窗我們需要哪些功能?
- 需要可以自己自定義樣式。因為每個彈窗會根據邏輯和需求的不同擁有不同的樣式。例如有些彈窗有title標題,有些只有message提示;有些有確定和取消按鈕,有些又只有一個確定按鈕。我們必須用一套程式碼來載入不同的樣式才行。
- 設定title或者message的內容。這裡可以根據傳入的不同id設定不同文字內容。
- 設定按鈕的點選事件
- 設定是否需要點選彈窗外部使得彈窗消失。
開始操作
分析完了需求之後我們便可以根據需求來擼程式碼了。
首先我們寫一個CommonDialog類讓他繼承Dialog。 此時我們必須複寫onCreat(),在onCreat()我麼進行一些設定操作。這裡我們設定setContentView()載入佈局樣式,設定setCancelable()是否點選彈窗以外使得彈窗消失。
public class CommonDialog extends Dialog {
private Context context;
private View view;
private boolean cancelTouchout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(view);
setCancelable(cancelTouchout);
}
}
複製程式碼
其實這時候我們就開始要編寫Builder構造者模式的程式碼了。
構造者模式,顧名思義,就是根據我們的需要往程式碼上新增需求。例如,我們需要設定title標題的內容,此時我們就新增上這個功能,如果需要設定message內容的功能我們也設定上這個功能。如果不需要則不新增這段程式碼。
先根據不同樣式載入不同的佈局。此時我們利用LayoutInflater來處理。佈局樣式由引數傳遞進來。
public Builder view(int resView) {
view = LayoutInflater.from(context).inflate(resView, null);
return this;
}
複製程式碼
其次,再根據是否可以點選彈窗外部使得彈窗消失。
public Builder cancelTouchout(boolean val) {
cancelTouchout = val;
return this;
}
複製程式碼
傳入的val若為true代表可以消失,如果傳入的為false則代表不能消失。
緊接著我們再來看看如果根據title和message來設定不同的內容。 這裡我們的引數設定為兩個,一個是需要設定內容的id,一個是設定內容的文字title/message。我們先通過findViewById去查詢到這個View中的控制元件,之後再根據文字內容將文字設定到控制元件上去。
//設定標題title
public Builder setTitle(int viewRes,String title){
TextView txtTitle = (TextView) view.findViewById(viewRes);
txtTitle.setText(title);
return this;
}
//設定內容message
public Builder setMessage(int viewRes,String message){
TextView txtMessage = (TextView)view.findViewById(viewRes);
txtMessage.setText(message);
return this;
}
複製程式碼
然後我們就該去設定點選事件了。 點選事件我們可以借鑑設定title和message的情況來處理,通過傳入一個點選控制元件的id來查詢id,之後通過View.OnClickListener來回撥這個點選事件處理點選邏輯即可。
public Builder addViewOnclick(int viewRes,View.OnClickListener listener){
view.findViewById(viewRes).setOnClickListener(listener);
return this;
}
複製程式碼
最後我們只需要把最後寫一個build返回一個CommonDialog即可。但是如果此時我們呼叫使用這個CommonDialog時你會發現我們不管如何設定載入的View,發現大小其實都是不變的。這是怎麼回事?其實這是因為我們的背景色一起被設定進入了View佈局中。如果此時我們把我們載入的View背景設定為黑色(#000000),就會神奇的發現,在View旁邊還有一些白色的存在。正是因為這些白色,導致了我們無論如何設定彈窗寬度都顯示的是原來的大小。如果你要設定為圓角,那更是不太可能。
那該如何處理這種情況?其實很簡單,我們僅僅需要設定一下將彈窗風格的style設定一個透明的背景即可處理好這種情況。
我們在value-style中設定一個style風格樣式,將背景設定為透明即可。
<!--Dialog將白色背景變透明-->
<style name="Dialog" parent="android:style/Theme.Dialog">
<item name="android:background">@android:color/transparent</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
</style>
複製程式碼
此時我們再在CommonDialog中設定一個style樣式,根據傳入的樣式來處理風格。
public Builder style(int resStyle) {
this.resStyle = resStyle;
return this;
}
複製程式碼
最後我們再寫兩個CommonDialog的構造方法,根據是否有傳入style來呼叫不同父類。完成操作。
private CommonDialog(Builder builder) {
super(builder.context);
context = builder.context;
cancelTouchout = builder.cancelTouchout;
view = builder.view;
}
private CommonDialog(Builder builder, int resStyle) {
super(builder.context, resStyle);
context = builder.context;
cancelTouchout = builder.cancelTouchout;
view = builder.view;
}
複製程式碼
到此我們的整個程式碼就全部操作完畢。
使用
使用起來也非常簡單,我們只需要建立一個CommonDialog.Builder根據不同的業務需求來新增不同操作即可。
CommonDialog build;
//dialog彈窗
private void dialog(){
build = new CommonDialog.Builder(this)
.view(R.layout.dialog)//設定彈窗的樣式layout
.style(R.style.Dialog) //設定主題,這裡可以將背景設為透明,這樣只顯示你需要顯示的dialog部分
.cancelTouchout(true) //設定點選dialog之外是否彈窗消失,true為消失,false為不消失
.setTitle(R.id.txt_title, "這是一個彈窗標題")//根據id來設定標題的顯示文字
.setMessage(R.id.txt_message, "這是一個彈窗訊息內容")//根據id來設定訊息內容的顯示文字
.addViewOnclick(R.id.txt_sure, new View.OnClickListener() {//處理確認點選事件
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "點選了確定按鈕", Toast.LENGTH_SHORT).show();
build.dismiss();
}
})
.addViewOnclick(R.id.txt_cancel, new View.OnClickListener() {//處理取消的點選事件
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "點選了取消按鈕", Toast.LENGTH_SHORT).show();
build.dismiss();
}
}).build();
build.show();
}
複製程式碼
程式碼已經上傳至github,只需將CommonDialog這個類複製到自己專案中再複製style中的Dialog即可使用,方便快捷。歡迎start。github傳送門
有興趣可以關注我的小專欄,學習更多職場產品思考知識:小專欄