Android自定義View之通用Dialog

目錄

前言

一、自定義DialogView

二、自定義Dialog管理類

三、使用

四、拓展


前言

之前寫過一篇《Android自定義通用的Dialog》,最近在整理文章時看到了,發現代碼其實可以簡化一下,所以本篇也是寫一個通用的Dialog,但是我們會對代碼做進一步的封裝,讓我們的代碼邏輯看起來更加簡潔清晰,好了,話不多說,一起來動手實現吧!

一、自定義DialogView

封裝思路:既然是封裝Dialog,那麼我們肯定是首先要考慮它的通用性,而不是每種不同的Dialog我們都要單獨寫一個類,在裏面定義它的方法,我們儘量要做到能夠統一管理,所以這裏我們考慮當UI改變時,我們只去替換xml佈局文件即可,對於主題樣式的展示我們使用統一定義的類。再一個就是Dialog的顯示位置,我們這裏考慮可能不同的需求需要顯示在屏幕的不同位置,所以這裏我們也考慮做到動態傳入。那麼基於這個大致的思路,我們來寫一個類繼承自系統的Dialog:

import android.app.Dialog;
import android.content.Context;
import android.view.Window;
import android.view.WindowManager;

/**
 * 作者:created by Jarchie
 * 時間:2019-11-12 21:24:08
 * 郵箱:[email protected]
 * 說明:自定義提示框
 */
public class DialogView extends Dialog {

    public DialogView(Context context,int layout, int style,int gravity) {
        super(context, style);
        setContentView(layout);
        Window window = getWindow();
        WindowManager.LayoutParams layoutParams = window.getAttributes();
        layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        layoutParams.gravity = gravity;
        window.setAttributes(layoutParams);
    }

}

對於它的構造參數我們不用全部都實現,因爲我們需要使用它的透明主題,所以這裏我使用了它的兩個參數的構造方法,super是調用了它父類的構造方法,兩個參數很明顯context和style,然後我們根據上面最開始的思路,我們再定義我們自己需要的參數,從代碼中可以看到那就是我們的layout佈局文件和gravity它的顯示位置,因爲這裏是調用了super,所以這裏我們自己的參數想怎樣傳都是可以的,你也可以繼續增加你需要的參數都是OK的,因爲父類的構造參數一定是會調用的。然後下面就是對方法內部的代碼做一個簡要的說明,都是大家很熟悉的東西了:

setContentView(layout):傳入layout設置我們的佈局;

getWindow():拿到它的父容器,爲下面做改變主題打基礎;

window.getAttributes():拿到window對象的屬性,返回的是一個LayoutParams;

layoutParams.width&layoutParams.height:設置它的寬和高,layoutParams.gravity是設置它的位置,使我們傳入的參數;

window.setAttributes:把屬性設置回去,這樣我們的簡單的自定義就完成了。

二、自定義Dialog管理類

這裏我們定義了一個類用來管理我們所有的Dialog,也就是第一步中我們所創建的DialogView,所以我這裏使用了單例模式進行創建,保證管理類實例唯一性。

既然是管理所有的Dialog,所以我們需要給它一些通用的方法,比如:初始化、顯示隱藏等,所以我們定義幾個方法:

initView():初始化Dialog,這裏直接返回一個DialogView的實例,構造方法中傳入的是DialogView的構造方法需要的參數,這裏主題我們在values下的style文件裏面定義了一個,內容也比較簡單:背景透明無標題,代碼如下:

<!--DialogView Theme Style-->
<style name="Theme_Dialog" parent="Theme.AppCompat.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="windowNoTitle">true</item>
</style>

然後我們重載一個方法,給了一個默認的居中顯示的位置,方便大多數情況下居中顯示的需求處理,所以對於居中顯示的可以直接調用我們的兩個參數的構造方法即可。

show():定義顯示Dialog的方法,判斷是否正在顯示,不是正在顯示的情況下才顯示。

hide():定義隱藏Dialog的方法,判斷是否正在顯示,正在顯示的情況下才隱藏。

具體的代碼如下所示:

import android.content.Context;
import android.view.Gravity;

import com.jarchie.resizeitem.R;
import com.jarchie.resizeitem.view.DialogView;


/**
 * 作者:created by Jarchie
 * 時間:2019-11-12 21:28:58
 * 郵箱:[email protected]
 * 說明:提示框管理類
 */
public class DialogManager {

    //單例模式
    private static volatile DialogManager mInstance = null;

    private DialogManager() {
    }

    public static DialogManager getInstance() {
        if (mInstance == null) {
            synchronized (DialogManager.class) {
                if (mInstance == null) {
                    mInstance = new DialogManager();
                }
            }
        }
        return mInstance;
    }

    public DialogView initView(Context mContext, int layout) {
        return new DialogView(mContext, layout, R.style.Theme_Dialog, Gravity.CENTER);
    }

    public DialogView initView(Context mContext, int layout, int gravity) {
        return new DialogView(mContext, layout, R.style.Theme_Dialog, gravity);
    }

    public void show(DialogView view){
        if (view!=null){
            if (!view.isShowing()){
                view.show();
            }
        }
    }

    public void hide(DialogView view){
        if (view !=null){
            if (view.isShowing()){
                view.dismiss();
            }
        }
    }

}

三、使用

寫完了上面這些呢,我們的自定義Dialog就已經寫完了,那我們怎麼使用它呢?其實很簡單,一起來看一下!

首先我們可以在Activity中定義一個全局變量DialogView的對象,比如:

private DialogView mCodeView;

然後在需要初始化的地方進行初始化,只需要一行代碼即可,傳入上下文對象和自定義的佈局文件:

mCodeView = DialogManager.getInstance().initView(this,R.layout.dialog_code_view_layout);

這樣就初始化完成了,你就可以在需要顯示或隱藏的地方通過DialogManager調用show和hide方法即可,傳入我們的DialogView對象:

DialogManager.getInstance().show(mCodeView); //顯示
DialogManager.getInstance().hide(mCodeView); //隱藏

如果需要對Dialog中的某個控件做事件處理,也很簡單,可以先獲取這個控件,然後就可以隨心所欲的處理監聽事件了:

TouchPictureView mPictureView = mCodeView.findViewById(R.id.mPictureView);
mPictureView.setViewResultListener(new TouchPictureView.OnViewResultListener() {
            @Override
            public void onResult() {
                //處理手勢擡起事件
            }
        });

四、拓展

這個拓展內容我這裏只說一下是什麼,代碼最後我會給出,但不會放在這裏,我想大家可以自己先做一下,然後再去和我的代碼對比一下,每個人有每個人的寫法,這個沒有標準答案,只要能實現功能都是OK的。現在我來說一下這個思維拓展的內容:

基於上面封裝的DialogView,製作一個加載提示框,上面圖片下面文字,思考一下怎麼實現?

就大致是這樣一個效果,幾乎所有app裏面都有的一個加載提示。。。。。。

我的實現是:自定義一個類LoadingView結合DialogView再封裝一層,單獨具有加載功能的DialogView,佈局很簡單上面一個圖片控件ImageView,下面一個文本控件TextView,構造方法中使用上面的方法對DialogView進行初始化,圖片使用屬性動畫做旋轉動畫,注意loading開始時旋轉,loading結束時停止旋轉,提供默認文本及開放式設置文本的api,提供顯示隱藏的api,整體邏輯就是這麼多,對這塊比較熟悉的童鞋可以直接略過。

夜已深,不多擾,文至此,關電腦!

哦對了,最後放個源碼地址—— LoadingView 類點擊查看,

因爲我前幾天寫另一個Demo的時候用到了這幾個類,所以就不再另外寫Demo了,直接把另一個Demo的地址放上:Android---RecyclerView之動畫(工具類)實現可展開列表 ,這個Demo中的內容也是挺值得一看的,有需要的可以把源碼clone下來看一下!

晚安了,各位!好夢!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章