【问题标题】:How to navigate nested DialogFragments using the navigation component without destroying the second one?如何使用导航组件导航嵌套的 DialogFragments 而不破坏第二个?
【发布时间】:2022-01-05 19:00:41
【问题描述】:

情况:

  1. 片段 A 导航到 DialogFragment B(单击按钮时)
  2. 在 B 的 PositiveButton 中的给定条件下 -> 导航到 DialogFragment C

问题:

当点击 DialogFragment B 的确认按钮时,B 会收到对该 DialogFragment 的 onDestroy 调用。 无论如何,这是有意的,当 B 不需要导航到 C 时没有问题。

但是:当 B 按请求导航到 C 时,会发生以下情况:

  • C 会在几分之一秒内弹出,然后消失
  • 并且导航控制器的当前位置不是 A。我需要一次后按才能再次到达 A

我也不希望导航控制器位于 A。我希望它位于显示 DialogFragment 的 C。

实施:

片段实现

class FragmentA : Fragment() {
...
    // is assigned as onClick listener to the button
    fun onClickButton() {
        if (findNavController().currentDestination?.id == R.id.FragmentANavId) {
            val action = FragmentADirections.actionFragmentAToDialogFragmentB()
            findNavController().navigate(action)
    }
}

// in separate file
class DialogFragmentB : DialogFragment() {
...
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val builder = MaterialAlertDialogBuilder(requireContext())
            ...
            .setPositiveButton("Save", { _, _ ->
                if (...) {
                    val action = DialogFragmentBDirections.actionDialogFragmentBToDialogFragmentC
                    findNavController().navigate(action)
                }
         return builder.create()
     }
}

class DialogFragmentC : DialogFragment() {
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val builder = MaterialAlertDialogBuilder(requireContext()) // also tried with requireActivity() as context
            ...
            .setPositiveButton("Confirm", { _, _ ->
                // code to handle the user confirmation
                }
         return builder.create()
     }
}

nav_graph.xml

    <fragment
        android:label="@string/some_text"
        android:name="...FragmentA"
        android:id="@+id/fragmentA" >
        <action
            android:id="@+id/action_fragmentA_to_fragmentDialogB"
            app:destination="@id/fragmentDialogB" />
    </fragment>

    // I put them into a nested graph
    <navigation android:id="@+id/dialogFragmentsNested"
        app:startDestination="@id/fragmentDialogB">
        <dialog
            android:id="@+id/fragmentDialogB"
            android:name="...FragmentDialogB">
            <action
                android:id="@+id/action_fragmentDialogB_to_fragmentDialogC"
                app:destination="@id/fragmentDialogC" />
        </dialog>
        <dialog
            android:id="@+id/fragmentDialogC"
            android:name="fragmentDialogC">
        </dialog>
    </navigation>

尝试解决方法:

  • 将 dialogFragments 分组为嵌套图 -> 仅结构元素,不影响对话框生命周期
  • 更新导航依赖
    implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0' // from 2.2.2
    implementation 'androidx.navigation:navigation-ui-ktx:2.3.0' // from 2.2.2
    
  • 将 dialogFragmentC 中的对话框上下文更改为 requireActivity()
  • 尝试查找相关问题

总结

当我从 DialogFragmentB 导航到 DialogFragmentC 时,两个 DialogFragment 都会收到一个 onDestroy 调用(如泄漏金丝雀所观察到的)。

我在这里遗漏了什么吗?你有什么建议吗?

如何在不立即关闭 DialogFragmentC(且无需用户交互)的情况下从 DialogFragmentB 移动到 DialogFragmentC?

【问题讨论】:

  • 您不应该在对话框片段中调用navigate()。实现对 FragmentA 的回调,并从那里导航到 DialogFragmentC。
  • @DanielNugent 在使用导航组件时,您建议如何实现回调?我知道您可以轻松地将论点从一个目的地传递到另一个目的地。但是您将如何实现在 Fragment 和 DialogFragment 之间实现回调呢?到目前为止,片段和对话框并不知道彼此。非常感谢您的建议
  • @DanielNugent 我仍在学习使用导航组件。我喜欢您可以使用“嵌套图”创建独立且可重用的单元。所以他们确实有一个明确的切入点,只能从那里开始。就我而言,这确实是有道理的:C 只能从 B 导航到。如果有可能,我想保持这种方式
  • @cewaphi 你找到解决办法了吗?

标签: android nested android-dialogfragment android-architecture-navigation


【解决方案1】:

对我有用的是在导航到 DialogFragmentC 之前调用 findNavController().navigateUp()

在 DialogFragmentB 中我写道:

class DialogFragmentB : DialogFragment() {
...
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val builder = MaterialAlertDialogBuilder(requireContext())
        ...
        .setPositiveButton("Save", { _, _ ->
            if (...) {

                findNavController().navigateUp()

                val action = DialogFragmentBDirections.actionDialogFragmentBToDialogFragmentC
                findNavController().navigate(action)
            }
         return builder.create()
     }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-16
    • 1970-01-01
    相关资源
    最近更新 更多