四、自定义dialog的使用以及封装

  大家好,我是爱吃土豆的土豆,不知道大家七夕晚上过得咋样啊,有对象的注意不要搞出人命了,没对象的来和土豆一起 new 对象。咳咳,因为公司事情确实多,所以就算我完成了一些案例,比如popupwindow啊 获取本地相册或者使用手机拍照啊 使用百度地图获取定位什么的,但是没什么时间记录一下,既然今天放假了,就不能再拖延下去了。既然前面都提到了popupwindow,地图定位什么的,那我们今天就不讲这些了,em。。,毕竟要对的起我们文章的标题嘛。
  进入正题,说起dialog,应该是安卓里面的常客了,因其小巧方便的特性,可以在程序的任何地方都可以使用。因此安卓程序也为我们提供默认样式的dialog,比如这样:


四、自定义dialog的使用以及封装_第1张图片
image.png

  所以昨天它是一个人过七夕的,别问我为什么。
  在实际项目中,我们大多使用自己定制的dialog,也就是所谓的自定义dialog。不过这篇文章不纯粹将如何去实现自定义的dialog,这时候又有好事者要问了,土豆,你是不是话痨,别人的文章都只说如何去实现自定义的dialog,你还要自己加点东西上去blabla。。。这位同学,你听我慢慢道来。
  其实项目中dialog基本用在比如网络请求时,告诉用户要耐心等待一下或者用户进行某项比较重要的操作时,弹出dialog让其确认,而土豆今天写的,就是项目中最常见的,confirmDialog,这样的dialog有一个title、一个msg、两个按钮组成,就像文章开头的系统默认样式的dialog一样,先来看看效果:


四、自定义dialog的使用以及封装_第2张图片
自定义dialog.gif

  em。。。虽然我使用了自己定义的样式,但是美观上。。。。。。。。
四、自定义dialog的使用以及封装_第3张图片
image.png

  可以看到在一个activity中,我们使用了两次自定义的dialog,神经比较大条的同学可能会写两次创建dialog的代码,因为标题啊,内容啊,button的点击事件都不一样,很难封装在一个方法中。这时候脑子转的快的同学会说了,如果真要封装的话,标题和内容我们可以通过方法传参解决,但是因为业务不同,所以button的点击事件很可能不同,所以还是较难封装。具体如何封装在一个activity,土豆这里不详细讲了,因为就算你实现了在一个activity中封装了dialog,但是如果其他activity如果也要使用相同的dialog,是不是直接以前写好的代码复制过去呢?(后面那个一直点头的同学,你不要太过分啊)再夸大点讲,如果一万个activity中都要用这个dialog,我们难道复制一万次相同的代码吗,当然是不,所以土豆今天要讲的是,一人购买,全家使用,呸,一次创建,各地使用。
  但是但是,在这之前,还是需要先说点其他东西,使用android studio的伙伴们都知道,在android studio中创建activity时,ide会为我们自动创建相应的布局并且自动关联,而且很贴心的为我们自动注册了活动,很方便。不知道各位有没有发现,其自动创建的活动是继承自AppCompatActivity,当然,你也可以手动修改让其继承Activity,那么,我们为什么不创建一个属于自己的activity,在这个activity中封装项目中所有activity都会进行的操作,比如,initData(),initView()这两个我们规范代码的方法,每次创建activity都要手动创建,太麻烦,封装封住,又比如,我们即将要讲的dialog,这个方法每个activity都可能会使用,所以也封装进去,这样我们所有的只要继承自这个activity的都可以使用此方法
  在这里,土豆把我们自己创建的activity命名为BaseActivity,意思是所有的activity的根据地,先放代码:

  package com.example.administrator.potato.activity;

import android.app.Activity;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import com.example.administrator.potato.interfaces.ConfirmDialogInterface;
import com.example.administrator.potato.R;

public abstract class BaseActivity extends Activity {
    protected Context mContext;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //获取上下文对象
        mContext=this;
    }
    /**
     * 初始视图
     * */
    protected abstract void initView();

    /**
     * 初始数据
     * */
    protected abstract void initData();

    /**
     * 显示确认框形式的dialog
     * @param title dialog的标题
     * @param msg dialog的消息
     * @param confirmDialogInterface 监听dialog确认键以及取消键的点击事件
     * */
    protected void showConfirmDialog(@Nullable String title, @Nullable String msg, @NonNull final ConfirmDialogInterface confirmDialogInterface){
        final AlertDialog.Builder builder=new AlertDialog.Builder(mContext);
        //加载布局
        View view=View.inflate(mContext,R.layout.dialog_confirm,null);
        //获取组件实例
        TextView textTitle=view.findViewById(R.id.textTitle);
        TextView textContent=view.findViewById(R.id.textContent);
        TextView textConfirm=view.findViewById(R.id.textConfirm);
        TextView textCancel=view.findViewById(R.id.textCancel);
        //设置标题
        textTitle.setText(title);
        //设置消息内容
        textContent.setText(msg);
        //设置需要显示的view
        builder.setView(view);
        //赋值给其父类以获取dismiss方法
        final AlertDialog alertDialog=builder.create();
        //显示dialog
        alertDialog.show();
        //设置确定按钮内容
        textConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //确认键业务逻辑处理接口
                confirmDialogInterface.onConfirmClickListener();
                //业务逻辑处理完毕使dialog消失
                alertDialog.dismiss();
            }
        });
        //设置取消按钮内容
        textCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //取消键业务逻辑处理接口
                confirmDialogInterface.onCancelClickListener();
                //业务逻辑处理完毕使dialog消失
                alertDialog.dismiss();
            }
        });

    }
}

  接口的代码:

package com.example.administrator.potato.interfaces;

/**
 * 作者:土豆
 * 创建日期:2018/8/16
 * 邮箱:[email protected]
 */

public interface ConfirmDialogInterface {
    //监听确认按钮点击事件
    void onConfirmClickListener();
    //监听取消按钮点击事件
    void onCancelClickListener();
}

  可以看到,我们把BaseActivity设置为抽象类,并且有两个抽象方法initData以及initView,还有一个属性Context,至于为啥要这样写,这里不详细讲,因为我们今天的主角是这个方法:

/**
     * 显示确认框形式的dialog
     * @param title dialog的标题
     * @param msg dialog的消息
     * @param confirmDialogInterface 监听dialog确认键以及取消键的点击事件
     * */
    protected void showConfirmDialog(@Nullable String title, @Nullable String msg, @NonNull final ConfirmDialogInterface confirmDialogInterface){
        final AlertDialog.Builder builder=new AlertDialog.Builder(mContext);
        //加载布局
        View view=View.inflate(mContext,R.layout.dialog_confirm,null);
        //获取组件实例
        TextView textTitle=view.findViewById(R.id.textTitle);
        TextView textContent=view.findViewById(R.id.textContent);
        TextView textConfirm=view.findViewById(R.id.textConfirm);
        TextView textCancel=view.findViewById(R.id.textCancel);
        //设置标题
        textTitle.setText(title);
        //设置消息内容
        textContent.setText(msg);
        //设置需要显示的view
        builder.setView(view);
        //赋值给其父类以获取dismiss方法
        final AlertDialog alertDialog=builder.create();
        //显示dialog
        alertDialog.show();
        //设置确定按钮内容
        textConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //确认键业务逻辑处理接口
                confirmDialogInterface.onConfirmClickListener();
                //业务逻辑处理完毕使dialog消失
                alertDialog.dismiss();
            }
        });
        //设置取消按钮内容
        textCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //取消键业务逻辑处理接口
                confirmDialogInterface.onCancelClickListener();
                //业务逻辑处理完毕使dialog消失
                alertDialog.dismiss();
            }
        });

    }

  这个方法就是用于实现自定义dialog的方法,如何实现的话,程序里面注释也写的很完善,我就不再赘述了,我这里只讲思路,讲逻辑。咳咳,大家都暂时不要睡觉了,下面的是重点,期末要考的:

1、自定义dialog无非是用我们自己创建的view通过build.setView()方法取代了系统预定的view,这里的view就指的是我们要显示的dialog的样子,比如在这篇文章中,我们自己的view写成这样的
四、自定义dialog的使用以及封装_第4张图片
image.png

布局代码就不贴出来了,很简单

2、由于我们使用了自己的view,所以我们只能先自己找到我们view的id,然后使用代码去操控它,比如

 //获取组件实例
        TextView textTitle=view.findViewById(R.id.textTitle);
        。。。。
 //设置标题
        textTitle.setText(title);

就像这样,title我们就可以通过从方法外部传入,这样我们就可以随心所欲让它显示我们想显示的内容了。同理,消息内容也可以这样设置
3、显示文字性的可以通过Textview.setText实现,但是点击事件的内容却是难以掌控的,但是对接口有了解的同学露出了回心笑容,我们可以把按钮的事件委托给接口,让实现这个接口的activity自己决定细节,有反应慢的同学可能暂时难以理解,暴躁的同学还会说,你说的啥玩意儿啊,听不懂。没关系,就打个比方吧,比如说土豆是一个饲养员,饲养了很多不同种类的动物,这些动物呢也很善解人意,我说啥它们都能听懂,我闲着无事,就给它们发了一个指令----“叫”,动物们收到指令了,于是鸭子就“嘎嘎”叫,鸡就“大爷,来玩啊”,呸,鸡就“咯咯咯”的叫,羊就“咩咩”的叫,那么,我只是定义了“叫”这个方法,但如何'叫",该怎么“叫”,不是我自己叫的吧,是接收到命令的动物们自己根据自己的实际情况发出了相应叫声。那好了,在这个例子中,我们来理一下对应关系:
饲养员土豆对应的是BaseActivity
指令“叫”对应的是 confirmDialogInterface.onConfirmClickListener();也就是接口
动物们不同的叫声对应的是不同的实现了调用了该接口的activity,因为具体如何叫是这些activity该解决的事情
下面,就贴出其中一个完整的activity的代码

package com.example.administrator.potato.activity;

import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

import com.example.administrator.potato.R;
import com.example.administrator.potato.interfaces.ConfirmDialogInterface;
import com.example.administrator.potato.utils.ToastMessage;

import butterknife.ButterKnife;
import butterknife.OnClick;

public class UseDialogActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_use_dialog);
        ButterKnife.bind(this);
        initView();
        initData();
    }

    @Override
    protected void initView() {

    }

    @Override
    protected void initData() {

    }

    @OnClick({R.id.button1, R.id.button2,R.id.button})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.button:
                AlertDialog.Builder builder=new AlertDialog.Builder(mContext);
                builder.setTitle("默认样式dialog")
                        .setMessage("我是颜值担当!!!")
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                            ToastMessage.toastSuccess("点击了确定键",true);
                            }
                        })
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ToastMessage.toastSuccess("点击了取消键",true);

                            }
                        })
                        .create()
                        .show();
                break;
            case R.id.button1:
                showConfirmDialog("来自土豆的提示", "这是第一个dialog", new ConfirmDialogInterface() {
                    @Override
                    public void onConfirmClickListener() {
                        Toast.makeText(mContext,"点击了第一个dialog的确认键",Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onCancelClickListener() {
                        Toast.makeText(mContext,"点击了第一个dialog的取消键",Toast.LENGTH_SHORT).show();
                    }
                });
                break;
            case R.id.button2:
                showConfirmDialog("温馨提示", "这是第二个dialog!!", new ConfirmDialogInterface() {
                    @Override
                    public void onConfirmClickListener() {
                        ToastMessage.toastSuccess("这是第二个dialog的确认键",true);
                    }

                    @Override
                    public void onCancelClickListener() {
                        ToastMessage.toastSuccess("这是第二个dialog的取消键",true);
                    }
                });
                break;
        }
    }
}

我们比较关注的应该是这段代码:

showConfirmDialog("来自土豆的提示", "这是第一个dialog", new ConfirmDialogInterface() {
                    @Override
                    public void onConfirmClickListener() {
                        Toast.makeText(mContext,"点击了第一个dialog的确认键",Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onCancelClickListener() {
                        Toast.makeText(mContext,"点击了第一个dialog的取消键",Toast.LENGTH_SHORT).show();
                    }
                });

  可以看到,我们只需要使用BaseActivity中的showConfirmDialog方法,然后将title,msg,以及新建一个接口用于实现button不同的点击事件即可,十分的方便,而且任意一个只要继承自我们自己的BaseActivity的activity都可以使用这个方法,是不是简化了很多代码,也让我们的程序变得更加整洁。当然,在同一个activity中也可以多次调用这个方法,毕竟动物们有不是只能有一种叫声,比如鸡,咳咳。。
  总结:
1、有一些追求的完美的同学可能会问,土豆,你这按钮的文字没有封装呀,我要是需要改变两个按钮的文字咋办呢?土豆会告诉你,封装方法和title的原理一样,无非是showConfirmDialog方法外传入一个参数,然后在showConfirmDialog中去改变对应的按钮的文字,你懂的
2、细心的同学可能会发现,我并没有在外部传入context,而是使用的BaseActivity的context,其实主要是为了方便啦,少穿点参数还是舒服的,但是请一定注意,不要用我们上次封装的那种Application的Context去启动dialog,会出错,至于出啥错,为啥会出错呢,自己去了解一下哟
3、启动dialog的时候,activity并没有走onResume生命周期哦
4、本项目的码云地址:https://gitee.com/fightPotato/potato.git

5、下一次讲和dialog同样常用的popupWindow,下次见

你可能感兴趣的:(四、自定义dialog的使用以及封装)