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,先看最终效果图

二、效果图

fd57a97d90c599bbbc222a2ca51831e7d6658dad

gif图比较模糊,直接扫二维码下载APK吧! 三、为什么选择DialogFragment?

DialogFragment继承自Fragment,即可以用Fragment来展示Dialog,相比于用AlertDialog或者DialogDialogFragment 更有优势:

 ●  当手机配置变化导致Activity重建时(比如旋转屏幕)或点击物理返回键时,DialogFragment可以管理好自己的生命周期

 ●  DialogFragment继承自Fragment,所以DialogFragment也可以当做一个内嵌的组件来使用,所以DialogFragment有更好的复用性

四、UML图

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

e2393d1de67671b0744ae7946377e53e788be3a0

五、使用文档

1、使用内置dialog:

 ●   内置一个Button的样式:
 new SYDialog.Builder(this)
.setTitle("我是标题")
.setContent("您好,我们将在30分钟处理,稍后通知您订单结果!")
.setPositiveButton(new IDialog.OnClickListener() {
@Override
public void onClick(IDialog dialog) {
dialog.dismiss();
}
})
.show();

效果图:

d7c6f386fdaaee6a8c1a7a21d64d46f82c99fa3d

内置二个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();

效果图:

04b6e3059af820e08645fc4c849e1cc6562ed423

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来保存多个DialogrequestShow()方法中首先会判断当前是否有正在显示的弹窗,如果有,则在队列中等待,否则从队列中取出并展示,并在队列中清空该数据,当一个Dialog展示完毕,会继续尝试在队列中取出Dialog并展示,直到队列是空为止。

六、源码地址

上述例子源码:
https://github.com/crazyqiang/AndroidStudy


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

本文作者:mmmqqq

本文来自云栖社区合作伙伴“安卓巴士Android开发者门户”,了解相关信息可以关注“安卓巴士Android开发者门户”。

相关文章
|
6月前
|
Java Maven Android开发
Android弹出dialog提示框演示
Android弹出dialog提示框演示
55 1
|
6月前
|
Android开发
Android 分享机顶盒项目的封装类《GridView》(二)(转)
Android 分享机顶盒项目的封装类《GridView》(二)(转)
45 2
|
4月前
|
XML Android开发 数据格式
Android 中如何设置activity的启动动画,让它像dialog一样从底部往上出来
在 Android 中实现 Activity 的对话框式过渡动画:从底部滑入与从顶部滑出。需定义两个 XML 动画文件 `activity_slide_in.xml` 和 `activity_slide_out.xml`,分别控制 Activity 的进入与退出动画。使用 `overridePendingTransition` 方法在启动 (`startActivity`) 或结束 (`finish`) Activity 时应用这些动画。为了使前 Activity 保持静止,可定义 `no_animation.xml` 并在启动新 Activity 时仅设置新 Activity 的进入动画。
81 12
|
3月前
|
Android开发 iOS开发
Android项目架构设计问题之将隐式跳转的逻辑进行抽象和封装如何解决
Android项目架构设计问题之将隐式跳转的逻辑进行抽象和封装如何解决
38 0
|
3月前
|
编解码 API 开发工具
Android平台轻量级RTSP服务模块二次封装版调用说明
本文介绍了Android平台上轻量级RTSP服务模块的二次封装实践,旨在简化开发流程,让开发者能更专注于业务逻辑。通过`LibPublisherWrapper`类提供的API,可在应用中轻松初始化RTSP服务、配置视频参数(如分辨率、编码类型)、启动与停止RTSP服务及流发布,并获取RTSP会话数量。此外,还展示了如何处理音频和视频数据的采集与推送。最后,文章提供了从启动服务到销毁资源的完整示例,帮助开发者快速集成实时流媒体功能。
|
4月前
|
XML Android开发 数据格式
Android面试题之DialogFragment中隐藏导航栏
在Android中展示全屏`DialogFragment`并隐藏状态栏和导航栏,可通过设置系统UI标志实现。 记得在布局文件中添加内容,并使用`show()`方法显示`DialogFragment`。
59 2
|
5月前
|
Android开发
Android中如何动态的调整Dialog的背景深暗
在Android开发中,Dialog和DialogFragment可通过设置`Window`的`backgroundDimAmount`来控制背景变暗,突出对话框。在DialogFragment的`onCreateDialog`或`onViewCreated`中,获取`Dialog`的`Window`,设置`LayoutParams.dimAmount`(例如0.5f)并添加`FLAG_DIM_BEHIND`标志。要动态调整,可保存`LayoutParams`并在需要时更新。对于Dialog,创建时直接设置同样属性。还可以通过定义主题样式设置背景模糊程度。
135 7
|
5月前
|
Android开发 Kotlin
kotlin安卓开发【Jetpack Compose】:封装SnackBarUtil工具类方便使用
GPT-4o 是一个非常智能的模型,比当前的通义千问最新版本在能力上有显著提升。作者让GPT开发一段代码,功能为在 Kotlin 中使用 Jetpack Compose 框架封装一个 Snackbar 工具类,方便调用
|
6月前
|
XML Java Android开发
Android 分享机顶盒项目的封装类《GridView》(三)(转)
Android 分享机顶盒项目的封装类《GridView》(三)(转)
37 2
|
6月前
|
Java Android开发 Kotlin
Android Dialog 弹出时,隐藏 navigation bar
Android Dialog 弹出时,隐藏 navigation bar
112 1