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下来看一下!

晚安了,各位!好梦!

发布了48 篇原创文章 · 获赞 47 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/JArchie520/article/details/103454231