当前位置: 首页 > news >正文

Android Dialog:Dialog和DialogFragment的区别?DialogFragment如何使用?源码解析

目录

在这里插入图片描述


一、Dialog和DialogFragment的区别

Android在DialogFragment推出后,就已经不推荐继续使用Dialog,可替换为DialogFragment:

  1. 更好的生命周期管理:DialogFragment能够自动处理Activity的生命周期事件,确保对话框在Activity重建时能够正确恢复。在Activity退出的时候会自动回收Dialog弹窗。
  2. 更高的灵活性:DialogFragment支持复杂的UI和逻辑操作,能够满足更多样化的需求。
  3. 更好的封装性:通过封装对话框的显示逻辑,DialogFragment提高了代码的可重用性和可维护性。
  4. 更好的用户体验:由于DialogFragment能够更好地处理配置更改,因此能够提供更稳定、更流畅的用户体验。

二、Dialog如何使用?

(1)如下是一个最简单的使用方法:

Dialog(this@SettingActivity).show()

(2)当然,我们不可能这样使用,而是会增加布局视图、动画:

<!-- res/layout/dialog_custom.xml -->  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:orientation="vertical"  android:padding="16dp">  <TextView  android:id="@+id/textViewMessage"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="这是一个自定义对话框"  android:textSize="18sp" />  <Button  android:id="@+id/buttonOk"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="确定" />  </LinearLayout>
// 假设这是Activity中的一个方法  
fun showCustomDialog() {  // 创建一个Dialog实例  val dialog = Dialog(this)  // 去除Dialog的标题  dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)  // 设置Dialog的内容布局  dialog.setContentView(R.layout.dialog_custom)  // 设置Dialog的窗口动画(需要先在res/values/styles.xml中定义动画样式)  //dialog.window?.setWindowAnimations(R.style.DialogAnimation)  // 获取布局中的组件并设置事件监听器  val textViewMessage = dialog.findViewById<TextView>(R.id.textViewMessage)  val buttonOk = dialog.findViewById<Button>(R.id.buttonOk)  // 设置按钮的点击事件监听器  buttonOk.setOnClickListener {  // 关闭Dialog  dialog.dismiss()  }  // 显示Dialog  dialog.show()  
}

(3)那么如何继承dialog来自定一个dialog呢?

import android.app.Dialog  
import android.content.Context  
import android.os.Bundle  
import android.view.LayoutInflater  
import android.view.View  
import android.view.Window  
import android.widget.Button  
import android.widget.TextView  // 自定义Dialog类  
class CustomDialog(context: Context) : Dialog(context) {  // 布局中的组件  private lateinit var textViewMessage: TextView  private lateinit var buttonOk: Button  //Dialog的初始化其实就是让我们去初始化自己的视图override fun onCreate(savedInstanceState: Bundle?) {  super.onCreate(savedInstanceState)  // 去除标题  requestWindowFeature(Window.FEATURE_NO_TITLE)  // 设置内容布局  setContentView(R.layout.dialog_custom)  // 初始化布局中的组件  textViewMessage = findViewById(R.id.textViewMessage)  buttonOk = findViewById(R.id.buttonOk)  // 设置按钮的点击事件监听器  buttonOk.setOnClickListener {  // 关闭Dialog  dismiss()  }  // (可选)设置Dialog的窗口动画  // window?.setWindowAnimations(R.style.DialogAnimation)  }  // 你可以添加更多的方法和属性来扩展你的Dialog  // 例如,一个方法来设置消息文本  fun setMessage(message: String) {  textViewMessage.text = message  }  
}  // 在你的Activity或Fragment中这样使用它  
fun showCustomDialog(context: Context) {  val customDialog = CustomDialog(context)  // (可选)设置消息文本  customDialog.setMessage("这是一个自定义对话框")  // 显示Dialog  customDialog.show()  
}

这个CustomDialog类直接继承了Dialog,并在其onCreate方法中设置了布局、初始化了组件,并设置了监听器。show()其实就是走Dialog的生命周期,然后做初始化工作,注意,show()之后才执行onCreate()。如下源码可以看出:

在这里插入图片描述

在这里插入图片描述


三、Dialog是什么,Window又是什么?

我们可以看一下Dialog的源码。

在这里插入图片描述

Dialog的构造方法中可以看出,Dialog实质上是个Window。

Dialog是Android中用于显示一个浮动窗口的类,这个窗口会覆盖在当前的活动(Activity)或应用程序的顶部。Dialog用于临时显示一些信息给用户,或者要求用户进行某些选择(如确认、选择列表项等)。Dialog可以包含各种控件,如按钮、文本输入框、列表视图等,以便与用户进行交互。

那么Window是什么?

Window是Android中更为抽象的一个概念,它代表了屏幕上的一块矩形区域,用于显示内容。在Android中,几乎所有的UI组件都是基于Window的,包括Activity、Dialog等。Activity实际上是一个特殊的Window,它拥有整个屏幕作为显示区域,并且可以在其上添加各种视图(Views)来构建用户界面。

Dialog与Window的区别:

Dialog与Window:Dialog内部通过PhoneWindow来实现窗口的显示,PhoneWindow是Window的具体实现类。Dialog在创建时会关联一个PhoneWindow对象,并通过这个对象来管理窗口的视图和布局。

WindowManager 是什么?

还有一个WindowManager,WindowManager负责将应用的用户界面显示在屏幕上,并管理窗口的创建、显示、隐藏、更新等操作。Dialog在创建时会关联一个Context(上下文),并通过这个Context获取WindowManager服务,进而与WindowManager绑定,实现窗口的添加和管理。


四、DialogFragment是什么?

DialogFragment 本质上是一个Fragment + Dialog,也就具有Fragment所拥有的生命周期,同时拥有Dialog的特点;在使用时,更容易通过生命周期回调来管理弹窗,对于复杂样式的弹窗,使用DialogFragment更加方便和高效。


五、DialogFragment如何使用

(1)创建xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="880dp"android:layout_height="420dp"android:layout_gravity="center"android:background="@drawable/home_rectangle_background"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"><TextViewandroid:id="@+id/home_textview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="120dp"android:text="是否立即关机?"android:textColor="#576478"android:textSize="42sp"android:textStyle="bold"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><TextViewandroid:id="@+id/tv_start_dev"android:layout_width="260dp"android:layout_height="100dp"android:gravity="center"android:text="立即开机"android:layout_marginTop="70dp"android:textSize="42sp"android:textColor="@color/white"android:background="@drawable/home_rectangle_blue_background"app:layout_constraintEnd_toStartOf="@+id/backstage_guideline"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/home_textview" /><TextViewandroid:id="@+id/tv_back"android:layout_width="260dp"android:layout_height="100dp"android:layout_marginTop="70dp"android:gravity="center"android:textColor="#569DF6"android:text="取消"android:textSize="42sp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="@+id/backstage_guideline"app:layout_constraintTop_toBottomOf="@+id/home_textview" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/backstage_guideline"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintGuide_percent="0.5" /></androidx.constraintlayout.widget.ConstraintLayout></androidx.constraintlayout.widget.ConstraintLayout>

(2)创建一个类继承自DialogFragment,然后给他指定布局文件
在 onCreateView() 方法中,加载弹窗的布局文件。
在 onViewCreated() 方法中,初始化弹窗的控件。

class MyDialogFragment: DialogFragment() {override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {dialog?.requestWindowFeature(Window.FEATURE_NO_TITLE)var view :View = inflater.inflate(R.layout.backstage_dialog_devonoff,container)return view}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)var tv :TextView= view.findViewById(R.id.tv_start_dev)}
}

(3)在Activity中进行使用。

 val myDialogFragment: MyDialogFragment= MyDialogFragment()myDialogFragment.show(supportFragmentManager, "MyDialogFragment")

在这里插入图片描述


六、DialogFragment源码解析

DialogFragment创建的时候,会有两个创建方法:onCreateDialog和onCreateView

class MyDialogFragment:DialogFragment() {override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {return super.onCreateDialog(savedInstanceState)}override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {return super.onCreateView(inflater, container, savedInstanceState)}
}

如果你在onCreateDialog和onCreateView都写了布局,那么会优先使用onCreateDialog里面的。源码这里我们可以看到。如果onCreateDialog不传递一个新的dialog,那么就会使用默认的,而布局,就是从onCreateView里面取,也就是requireView方法。
在这里插入图片描述在这里插入图片描述

如果onCreateDialog不重写,会自动创建一个空白的dialog。view使用的就是oncreateView的:如下:

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • MATLAB进行天线阵列方向图综合
  • 海外域名自动手动免费续费ssl证书
  • 对象存储数据库minio的持久化存储
  • 模拟算法专题——算法介绍算法讲解力扣实战应用
  • Android中使用eBPF跟踪 FD打开与关闭
  • HTTP“请求”和“响应”的报头及正文详解
  • BUUCTF—[网鼎杯 2020 朱雀组]phpweb
  • 【Spring Boot 3】【Web】解析获取HTTP请求参数
  • 828华为云征文|部署私有云和文档管理系统 Kodcloud
  • 【C++】static作用总结
  • Harmony TextInput实现带有提示语的Text效果
  • Linux之MySQL日志
  • java 中简单实现异步的几种方法
  • Falcon Mamba:首个高效的无注意力机制7B模型
  • knime和Python两种解法提取斜杠(/)或反斜杠(\)分隔前后数据
  • C# 免费离线人脸识别 2.0 Demo
  • flutter的key在widget list的作用以及必要性
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • Magento 1.x 中文订单打印乱码
  • node 版本过低
  • pdf文件如何在线转换为jpg图片
  • php中curl和soap方式请求服务超时问题
  • Vue.js-Day01
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 经典排序算法及其 Java 实现
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 如何打造100亿SDK累计覆盖量的大数据系统
  • 译米田引理
  • 函数计算新功能-----支持C#函数
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • # centos7下FFmpeg环境部署记录
  • # 数仓建模:如何构建主题宽表模型?
  • #Linux(Source Insight安装及工程建立)
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (k8s中)docker netty OOM问题记录
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (面试必看!)锁策略
  • (四)c52学习之旅-流水LED灯
  • (转载)CentOS查看系统信息|CentOS查看命令
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • .gitignore文件忽略的内容不生效问题解决
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • .net的socket示例
  • .NET建议使用的大小写命名原则
  • .NET连接MongoDB数据库实例教程
  • .NET企业级应用架构设计系列之结尾篇
  • .NET中winform传递参数至Url并获得返回值或文件
  • .sdf和.msp文件读取
  • [ IO.File ] FileSystemWatcher
  • [ vulhub漏洞复现篇 ] Grafana任意文件读取漏洞CVE-2021-43798