天天看点

Android基于DialogFragment封装一个通用的Dialog

一、背景

Dialog是项目中最常用的一个功能之一了,接手项目的时候发现项目中是封装了一个dialog的,但是发现是用单例封装的,大致如下:

private MyDialog() {

}

public static MyDialog getInstance() {
return DialogHolder.instance;

}

private static class DialogHolder {
private static MyDialog instance = new MyDialog();

}

public void show(){}
public void dismiss(){}
           

使用单例除了可能会有内存泄漏问题,在使用过程中还发现一个问题:不同页面的dialog可以相互影响,想想也对,因为全局只有一个

dialog

嘛,项目中有一个场景:A页面跳B页面,一进B页面的

onCreate()

时需要弹一个dialog,发现每次都弹不出来,debug发现原来在A页面的

onStop()

方法里调用了

dismiss()

方法,A页面跳B页面生命周期走的是:

A页面: onPause()

B页面: onCreate()

B页面: onStart()

B页面: onResume()

A页面: onStop()
           

所以原因也找到了,每次在B的

onCreate()

里面刚调用了

show()

,紧接着又调用了A的

onStop()

中的

dismiss()

给关掉了,用单例方式显然不太合适。趁着版本大改版,花了点时间重新撸了一个。根据我们的项目需要,调研了下,大概需要符合以下场景:

1、

不用提供布局,内置项目中常用默认的样式

2、 

支持自定义复杂的布局、动画、对话框大小、背景色等设置

3、

统一管理多个dialog并顺序弹出

第一点:大部分情况下,使用对话框的样式都是一致的,所以内置了默认的

dialog

样式,可以避免调用方每次再去找布局文件,尽可能的简化调用。ps:内置

dialog

样式可以根据需求自行修改。

第二点:如果需要自定义复杂的布局,需要支持布局子View的创建及一系列交互事件。

第三点: 项目中有个需求,可能一次会产生多个

dialog

,需要依次弹出

dialog

基于以上需求点,使用

DialogFragment

封装了一个通用

Dialog

——

SYDialog

,先看最终效果图

二、效果图
Android基于DialogFragment封装一个通用的Dialog

gif图比较模糊,直接扫二维码下载APK吧!

三、为什么选择DialogFragment?

DialogFragment

继承自

Fragment

,即可以用

Fragment

来展示

Dialog

,相比于用

AlertDialog

或者

Dialog

DialogFragment

 更有优势:

 ●  当手机配置变化导致

Activity

重建时(比如旋转屏幕)或点击物理返回键时,

DialogFragment

可以管理好自己的生命周期

 ●  

DialogFragment

Fragment

,所以

DialogFragment

也可以当做一个内嵌的组件来使用,所以

DialogFragment

有更好的复用性

四、UML图

用一个UML图大致来表示一下类之间的关系:

Android基于DialogFragment封装一个通用的Dialog
五、使用文档 1、使用内置dialog:

 ●  内置一个Button的样式:

new SYDialog.Builder(this)

.setTitle("我是标题")

.setContent("您好,我们将在30分钟处理,稍后通知您订单结果!")

.setPositiveButton(new IDialog.OnClickListener() {
@Override
public void onClick(IDialog dialog) {

dialog.dismiss();

}

})

.show();
           

效果图:

Android基于DialogFragment封装一个通用的Dialog

内置二个Button的样式:

new SYDialog.Builder(this)

.setTitle("我是标题")

.setContent("您好,我们将在30分钟处理,稍后通知您订单结果!")

.setPositiveButton(new IDialog.OnClickListener() {
@Override
public void onClick(IDialog dialog) {

dialog.dismiss();

}

})

.setNegativeButton(new IDialog.OnClickListener() {
@Override
public void onClick(IDialog dialog) {

dialog.dismiss();

}

})

.show();
           
Android基于DialogFragment封装一个通用的Dialog
2、使用自定义布局的样式:
new SYDialog.Builder(this)

.setDialogView(R.layout.layout_dialog)//设置dialog布局

.setAnimStyle(R.style.translate_style)//设置动画 默认没有动画

.setScreenWidthP(0.85f) //设置屏幕宽度比例 0.0f-1.0f

.setGravity(Gravity.CENTER)//设置Gravity

.setWindowBackgroundP(0.2f)//设置背景透明度 0.0f-1.0f 1.0f完全不透明

.setCancelable(true)//设置是否屏蔽物理返回键 true不屏蔽 false屏蔽

.setCancelableOutSide(true)//设置dialog外点击是否可以让dialog消失

.setBuildChildListener(new IDialog.OnBuildListener() {
//设置子View
@Override
public void onBuildChildView(final IDialog dialog, View view, int layoutRes) {
//dialog: IDialog
//view: DialogView
//layoutRes :Dialog的资源文件 如果一个Activity里有多个dialog 可以通过layoutRes来区分
final EditText editText = view.findViewById(R.id.et_content);

Button btn_ok = view.findViewById(R.id.btn_ok);

btn_ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

String editTextStr = null;
if (!TextUtils.isEmpty(editText.getText())) {

editTextStr = editText.getText().toString();

}

dialog.dismiss();

Toast.makeText(MyApplication.getApplication(), editTextStr, Toast.LENGTH_SHORT).show();

}

});

}

}).show();
           

代码中注释已经很详细了,如果是自定义布局并且需要处理交互事件,可以通过设置

setBuildChildListener

并实现其回调,并在回调接口中创建子View并处理交互事件,使用起来还是很方便的。

3、统一管理多个Dialog依次弹出
SYDialog.Builder builder1 = new SYDialog.Builder(this);

SYDialog.Builder builder2 = new SYDialog.Builder(this)
//添加第一个Dialog

SYDialogsManager.getInstance().requestShow(new DialogWrapper(builder1));
//添加第二个Dialog

SYDialogsManager.getInstance().requestShow(new DialogWrapper(builder2));
           

DialogWrapper

 来包装一层

Dialog

,方便后续添加数据信息。

SYDialogsManager

通过单例来实现,确保只有一个实例,内部有一个容器队列

ConcurrentLinkedQueue

来保存多个

Dialog

requestShow()

方法中首先会判断当前是否有正在显示的弹窗,如果有,则在队列中等待,否则从队列中取出并展示,并在队列中清空该数据,当一个

Dialog

展示完毕,会继续尝试在队列中取出

Dialog

并展示,直到队列是空为止。

六、源码地址

上述例子源码:

https://github.com/crazyqiang/AndroidStudy

原文发布时间为:2018-09-26

本文作者:mmmqqq

本文来自云栖社区合作伙伴“

安卓巴士Android开发者门户

”,了解相关信息可以关注“

”。

继续阅读