動手造輪子——用Builder模式擼一個通用版本的Dialog

前言

在Android開發中咱們經常須要使用Dialog來處理一些彈窗操做。雖然Android系統自己爲咱們封裝了一個自帶的彈窗Dialog,可是因爲Android操做系統的不一樣,致使了每一個手機彈窗頁面的不一樣,以致於咱們很難用系統的去統同樣式。而且UI會以爲系統的彈窗過於醜陋,但願本身來作一個因而咱們便須要本身來處理一個Dialog彈窗。今天叫你們利用Builder構造者模式本身來封裝一個彈窗Dialog。android

需求分析

首先肯定一下,彈窗咱們須要哪些功能?git

  1. 須要能夠本身自定義樣式。由於每一個彈窗會根據邏輯和需求的不一樣擁有不一樣的樣式。例若有些彈窗有title標題,有些只有message提示;有些有肯定和取消按鈕,有些又只有一個肯定按鈕。咱們必須用一套代碼來加載不一樣的樣式才行。
  2. 設置title或者message的內容。這裏能夠根據傳入的不一樣id設置不一樣文字內容。
  3. 設置按鈕的點擊事件
  4. 設置是否須要點擊彈窗外部使得彈窗消失。

開始操做

分析完了需求以後咱們即可以根據需求來擼代碼了。github

首先咱們寫一個CommonDialog類讓他繼承Dialog。 此時咱們必須複寫onCreat(),在onCreat()我麼進行一些設置操做。這裏咱們設置setContentView()加載佈局樣式,設置setCancelable()是否點擊彈窗之外使得彈窗消失。bash

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構造者模式的代碼了。ide

構造者模式,顧名思義,就是根據咱們的須要往代碼上添加需求。例如,咱們須要設置title標題的內容,此時咱們就添加上這個功能,若是須要設置message內容的功能咱們也設置上這個功能。若是不須要則不添加這段代碼。佈局

先根據不一樣樣式加載不一樣的佈局。此時咱們利用LayoutInflater來處理。佈局樣式由參數傳遞進來。學習

public Builder view(int resView) {
            view = LayoutInflater.from(context).inflate(resView, null);
            return this;
        }
複製代碼

其次,再根據是否能夠點擊彈窗外部使得彈窗消失。ui

public Builder cancelTouchout(boolean val) {
            cancelTouchout = val;
            return this;
        }
複製代碼

傳入的val若爲true表明能夠消失,若是傳入的爲false則表明不能消失。this

緊接着咱們再來看看若是根據title和message來設置不一樣的內容。 這裏咱們的參數設置爲兩個,一個是須要設置內容的id,一個是設置內容的文字title/message。咱們先經過findViewById去查找到這個View中的控件,以後再根據文字內容將文字設置到控件上去。spa

//設置標題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傳送門

有興趣能夠關注個人小專欄,學習更多職場產品思考知識:小專欄

相關文章
相關標籤/搜索