当前位置: 首页 > 知识库问答 >
问题:

使用导航架构组件在片段中显示备份/备份确认

田曜瑞
2023-03-14

我正在使用Android的导航架构组件。

对于我的一个片段,我希望拦截“后退”和“向上”导航,以便在放弃用户未保存的任何更改之前显示一个确认对话框。(编辑事件详细信息后按back/up时的行为与默认日历应用程序相同)

我目前的方法(未经测试)如下:

对于“向上”导航,我覆盖片段上的选项ItemSelected:

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
    if(item?.itemId == android.R.id.home) {
        if(unsavedChangesExist()) {
            // TODO: show confirmation dialog
            return true
        }
    }
    return super.onOptionsItemSelected(item)
}

为了“返回”导航,我在片段及其活动之间创建了一个自定义接口和回调系统:

interface BackHandler {
    fun onBackPressed(): Boolean
}

class MainActivity : AppCompatActivity() {
    ...

    val backHandlers: MutableSet<BackHandler> = mutableSetOf()

    override fun onBackPressed() {
        for(handler in backHandlers) {
            if(handler.onBackPressed()) {
                return
            }
        }
        super.onBackPressed()
    }

    ...
}

class MyFragment: Fragment(), BackHandler {
    ...

    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is MainActivity) {
            context.backHandlers.add(this)
        }
    }

    override fun onDetach() {
        (activity as? MainActivity)?.backHandlers?.remove(this)
        super.onDetach()
    }

    override fun onBackPressed(): Boolean {
        if(unsavedChangedExist()) {
            // TODO: show confirmation dialog
            return true
        }
    }

    ...
}

对于这样一件简单的事情来说,这一切都是相当粗糙和陈词滥调的。有更好的方法吗?

共有3个答案

宿建本
2023-03-14

对于向上导航,只需覆盖OnOptions ItemSelected()

override fun onOptionsItemSelected(item: MenuItem): Boolean =
    when (item.itemId) {
        android.R.id.home -> {
            showDialog() // show your dialog here
            true
        }
        else -> super.onOptionsItemSelected(item)
}
杜嘉木
2023-03-14

使用导航架构组件,您可以执行以下操作:

  1. 告诉你的活动将home按钮(后退箭头)上的所有向上点击发送给任何收听它的人。这会影响你的活动
override fun onOptionsItemSelected(item: MenuItem): Boolean {
     if (item.itemId == android.R.id.home) {
         onBackPressedDispatcher.onBackPressed()
         return true
     }
     return super.onOptionsItemSelected(item)
}
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        requireActivity().onBackPressedDispatcher.addCallback(this) {
           if (*condition for showing dialog here*) {
               // Show dialog
           } else {
               // pop fragment by calling function below. Analogous to when the user presses the system UP button when the associated navigation host has focus.
               findNavController().navigateUp()
           }
        }
    }
陆烨烁
2023-03-14

截至androidx。appcompat:appcompat:1.1.0-beta01,为了拦截带有导航组件的后退按钮,您需要在BackpressedDispatcher上添加一个回调。此回调必须扩展OnBackPressedCallback,并覆盖handleOnBackPressedOnBackPressedDispatcher遵循责任链模式来处理回调。换句话说,如果您将回调设置为enabled,则只会执行回调。否则,OnBackPressedDispatcher将忽略它并继续下一个回调,依此类推,直到它找到一个已启用的回调(例如,当您有多个回调时,这可能很有用)。更多信息请点击此处。

因此,为了显示您的对话框,您必须执行类似的操作:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  super.onViewCreated(view, savedInstanceState)

  val callback = object : OnBackPressedCallback(true /** true means that the callback is enabled */) {
    override fun handleOnBackPressed() {
        // Show your dialog and handle navigation
    }
  }

  // note that you could enable/disable the callback here as well by setting callback.isEnabled = true/false

  requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, callback)
}

至于向上按钮,似乎(至少目前)没有太多的可能性。到目前为止,我能找到的使用导航组件的唯一选择是为导航本身添加一个侦听器,它将同时处理两个按钮:

navController.addOnDestinationChangedListener { navController, destination ->
  if (destination.id == R.id.destination) {
    // do your thing
  }
}

无论如何,这有一个警告,即允许添加侦听器的活动或片段知道可能不应该知道的目的地。

 类似资料:
  • 我正在我的应用程序中尝试导航架构组件。早些时候,我使用片段事务来实现以下功能。基本上,我想从导航。 碎片- 如果我正在使用导航组件并尝试 然后结果是FragmentA被FragmentB替换并且背景片段不可见。 我想知道一个解决方案,如果导航架构组件允许的话。 附言:我听说过嵌套导航主机,但从内部使用它好吗。 更新: FragmentB将有进一步交易的行动,例如: 碎片- 当用户按下后退按钮时,片

  • 我正试图在现有的应用程序中实现新的Android导航组件。我有两个片段除了名字外都是一样的。当我将startDestination设置为fragment2时,片段似乎显示正确。当startDestination设置为fragment1时,我看不到膨胀的视图,但我确实看到了“Fragment 1 created”toast。 我做错了什么? 导航图。xml 主活动布局: Fragment1布局: 依

  • 是否可以将新的导航架构组件与DialogFragment一起使用?我必须创建自定义导航器吗? 我很乐意将它们与导航图中的新功能结合使用。

  • 数据税务文件规定 当表模式存在时,Cassandra只能从快照恢复数据。如果您尚未备份该模式,[...] 架构的完整备份需要什么?简单地备份< code >系统密钥空间?

  • 我们为您原片导出功能,只有开通原片备份功能,才可以使用导出功能。 点击导出,可导出该视频原片到本地,尚在处理状态视频,需等处理结束后方可导出。

  • 我正在使用BottomSheetDialogFraenge显示几个自定义设置的。 要求: 当我点击任何选项卡在BottomSheetDialogFraance我替换的片段,并将其添加到backstack,以便当用户点击的onBackPress或向上的行动,它应该回到最后设置的BottomSheetDialogFraank的片段。 我想使用导航架构组件来简化我的事务。 问题:如果我使用导航架构组件从