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

简介: DialogFragment是Android中用于创建弹窗的特殊Fragment,继承自Fragment。使用步骤包括:1. 创建子类,2. 在onCreateView加载布局,3. onViewCreated初始化控件,4. 通过show方法显示。示例代码展示了一个基本的DialogFragment及其布局。此外,文中还解答了三个常见问题:如何设置弹窗宽度为match_parent,如何使弹窗位于屏幕底部,以及如何去除弹窗四周的默认padding。每个问题都提供了相应的解决方案,涉及在onStart中调整窗口参数和设置自定义样式。

一、DialogFragment 简介

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

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

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

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

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 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 中添加以下代码:

// 创建弹窗实例
SimpleDialogFragment dialogFragment = new SimpleDialogFragment();

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

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

二、几个小问题的解法

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

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

image.png

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

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

解决方案

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)
    }
}

image.png

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

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)
    }
}

image.png

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

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

image.png

解决方案如下

首先,创建一个自定义的样式,去掉 padding。在 res/values/styles.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() 方法中,设置该样式:

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)
    }
}

运行效果如下:

image.png

(完)

相关文章
|
Android开发 开发者
Android中弹框如何设计成全屏的
本文介绍在Android中实现全屏对话框的方法,包括使用`Dialog`和`DialogFragment`两种方式。通过设置对话框无标题、调整布局参数及使用透明背景实现全屏效果。适用于希望提升应用交互体验的开发者。
730 0
|
XML Java Android开发
Android关于BottomNavigationView效果实现指南
本文详细介绍了Android中BottomNavigationView的实现与定制方法,涵盖颜色设置、图标修改、字体大小调整及多色图标处理等问题。通过XML和Java代码两种方式,解决图标颜色变化、点击效果等问题,并提供去除ActionBar的实现步骤。适合初学者及进阶开发者参考,助力打造更美观、功能丰富的底部导航栏。文末附源码,方便实践操作。
1275 28
Android关于BottomNavigationView效果实现指南
|
缓存 Android开发 iOS开发
Kotlin跨平台Compose Multiplatform实战指南
Kotlin Multiplatform (KMP) 结合 Compose Multiplatform,助力开发者用一套代码构建跨平台应用(Android、iOS、桌面和 Web)。本文提供实战指南,涵盖环境搭建、项目结构、共享 UI 编写、平台适配、状态管理及资源处理等内容。通过 expect/actual 处理差异,借助官方文档与示例项目学习,减少重复代码,优化多平台开发体验。
3039 18
|
XML 搜索推荐 Android开发
Android改变进度条控件progressbar的样式(根据源码修改)
本文介绍了如何基于Android源码自定义ProgressBar样式。首先分析了系统源码中ProgressBar样式的定义,发现其依赖一张旋转图片实现动画效果。接着分两步指导开发者实现自定义:1) 模仿源码创建一个旋转动画XML文件(放置在drawable文件夹),修改图片为自定义样式;2) 在UI控件中通过`indeterminateDrawable`属性应用该动画。最终实现简单且个性化的ProgressBar效果,附带效果图展示。
714 2
|
Android开发 开发者
Android中Dialog位置+样式的设置
本文介绍了在Android开发中如何设置Dialog的位置和样式。通过自定义`MyDialog`类,可以灵活调整Dialog的显示位置,例如将其固定在屏幕底部,并设置宽度匹配父布局。同时,文章还展示了如何模仿Android原生Dialog样式,通过定义`MyDialogStyle`去除标题栏、设置背景透明度、添加阴影效果以及配置点击外部关闭等功能,从而实现更加美观和符合需求的Dialog效果。代码示例详细,便于开发者快速上手实现。
711 2
|
API Android开发 开发者
Android经典实战之用WindowInsetsControllerCompat方便的显示和隐藏状态栏和导航栏
本文介绍 `WindowInsetsControllerCompat` 类,它是 Android 提供的一种现代化工具,用于处理窗口插入如状态栏和导航栏的显示与隐藏。此类位于 `androidx.core.view` 包中,增强了跨不同 Android 版本的兼容性。主要功能包括控制状态栏与导航栏的显示、设置系统窗口行为及调整样式。通过 Kotlin 代码示例展示了如何初始化并使用此类,以及如何设置系统栏的颜色样式。
1216 2
|
调度 Android开发 UED
Android经典实战之Android 14前台服务适配
本文介绍了在Android 14中适配前台服务的关键步骤与最佳实践,包括指定服务类型、请求权限、优化用户体验及使用WorkManager等。通过遵循这些指南,确保应用在新系统上顺畅运行并提升用户体验。
1309 6
|
编解码 测试技术 Android开发
Android经典实战之用 CameraX 库实现高质量的照片和视频拍摄功能
本文详细介绍了如何利用CameraX库实现高质量的照片及视频拍摄功能,包括添加依赖、初始化、权限请求、配置预览与捕获等关键步骤。此外,还特别针对不同分辨率和帧率的视频拍摄提供了性能优化策略,确保应用既高效又稳定。
2094 1
Android经典实战之用 CameraX 库实现高质量的照片和视频拍摄功能
|
Java Android开发
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
4000 1
|
XML 存储 Android开发
Android实战经验之Kotlin中快速实现MVI架构
本文介绍MVI(Model-View-Intent)架构模式,强调单向数据流与不可变状态管理,提升Android应用的可维护性和可测试性。MVI分为Model(存储数据)、View(展示UI)、Intent(用户动作)、State(UI状态)与ViewModel(处理逻辑)。通过Kotlin示例展示了MVI的实现过程,包括定义Model、State、Intent及创建ViewModel,并在View中观察状态更新UI。
853 12