DialogFragment 使用指南:几个小问题的解法

一、DialogFragment 简介

DialogFragment 是 Android 中的一个特殊的 Fragment,通常用于创建和显示弹窗。DialogFragment 继承自 Fragment,因此具有 Fragment 的所有特性。

DialogFragment 的使用非常简单,只需要如下几步:

  1. 创建 DialogFragment 的子类。
  2. onCreateView() 方法中,加载弹窗的布局文件。
  3. onViewCreated() 方法中,初始化弹窗的控件。
  4. 使用 show() 方法显示弹窗。

以下是一个简单的 DialogFragment 示例:

java 复制代码
public class SimpleDialogFragment extends DialogFragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_simple_dialog, container, false);

        return view;
    }
}

fragment_simple_dialog.xml 布局文件如下:

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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="500dp"
        android:gravity="center"
        android:text="测试弹窗"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

要使用该示例,需要在 Activity 中添加以下代码:

java 复制代码
// 创建弹窗实例
SimpleDialogFragment dialogFragment = new SimpleDialogFragment();

// 显示弹窗
dialogFragment.show(getSupportFragmentManager(), "SimpleDialogFragment");

该代码将创建一个 SimpleDialogFragment 实例,并使用 show() 方法显示弹窗。

二、几个小问题的解法

问题1:弹窗宽度设置为 match_parent 没有效果

明明我的布局里面设置的 layout_widthmatch_parent ,但是运行起来发现弹窗的内容宽度却是 wrap_content 的效果。运行效果如下图这样拉跨:

原因是当我们以布局 View 创建 DialogFragment 时。在 View 添加后,对话框最外层的 ViewGroup 并不知道我们导入的 View 所需要的的宽度(也就是说在 在 onCreateView 和 onViewCreated 方法里都不知道需要宽度)。

所以我们需要在 onStart 生命周期里修改一下对话框尺寸参数。

解决方案

kotlin 复制代码
class SimpleDialogFragment : DialogFragment(){
    companion object {
        const val TAG = "SimpleDialogFragment"
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View {
        return inflater.inflate(R.layout.layout_simple_dialog_fragment, container, false)
    }

    override fun onStart() {
        super.onStart()
        val window = dialog?.window
        // 设置宽度为铺满
        window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
    }
}

问题2:如何设置弹窗布局内容位于屏幕底部

kotlin 复制代码
class SimpleDialogFragment : DialogFragment(){
    companion object {
        const val TAG = "SimpleDialogFragment"
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View {
        return inflater.inflate(R.layout.layout_simple_dialog_fragment, container, false)
    }

    override fun onStart() {
        super.onStart()
        val window = dialog?.window
        // 设置宽度为铺满
        window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        // 设置布局内容显示在底部
        window?.setGravity(Gravity.BOTTOM)
    }
}

问题3:弹窗四周默认的 padding 如何去掉

在经过上面两步设置后,基本满足我们的要求了,不过还有点小瑕疵,在弹窗四周还有一个默认的 padding 🤪:

解决方案如下

首先,创建一个自定义的样式,去掉 padding。在 res/values/styles.xml 文件中,添加如下代码:

xml 复制代码
<style name="DialogFragmentNoPaddingStyle" parent="Theme.AppCompat.Light.Dialog">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:paddingLeft">0dp</item>
        <item name="android:paddingRight">0dp</item>
        <item name="android:paddingTop">0dp</item>
        <item name="android:paddingBottom">0dp</item>
    </style>

然后,在 DialogFragment 的 onCreate() 方法中,设置该样式:

kotlin 复制代码
class SimpleDialogFragment : DialogFragment(){
    companion object {
        const val TAG = "SimpleDialogFragment"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 设置 Style
        setStyle(STYLE_NO_FRAME, R.style.DialogFragmentNoPaddingStyle)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View {
        return inflater.inflate(R.layout.layout_simple_dialog_fragment, container, false)
    }

    override fun onStart() {
        super.onStart()
        val window = dialog?.window
        // 设置宽度为铺满
        window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        // 设置布局内容显示在底部
        window?.setGravity(Gravity.BOTTOM)
    }
}

运行效果如下:

(完)

相关推荐
parade岁月9 分钟前
倒反天罡!押注 React Native 6 年后,Shopify 又回到了原生开发
android·前端·ios
邪修king10 分钟前
MySQL 数据库(三):表级操作实战:增删查改全实例演示 + 企业实操红线规范
android·数据库·mysql
七夜zippoe19 分钟前
从 Prompt Engineering 到 Agent Engineering:开发范式的代际跃迁
android·ai·prompt·agent·engineering
音视频开发进阶27 分钟前
DuoShot:一次拍摄,让精彩多一种表达
android·duoshot
我命由我123451 小时前
Android 控件 - ListAdapter
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
一笑的小酒馆9 小时前
Androidiot开发之猫脸识别
android
三84411 小时前
PHP Session 反序列化(2):漏洞根因 —— 序列化处理器错位与对象注入
android·web安全·php·反序列化·session
天空之城--11 小时前
Android行业一周动态:编码趋势与行业资讯汇总
android·性能优化·架构·kotlin·android jetpack
Co_Hui13 小时前
Android Handler 内存泄漏分析
android
张小姐的猫14 小时前
【AI大模型接入SDK】 —— Gemini接入封装
android·数据结构·数据库·c++·人工智能·python