我正在使用Android的导航架构组件。
对于我的一个片段,我希望拦截“后退”和“向上”导航,这样我就可以在放弃用户任何未保存的更改之前显示一个确认对话框。(当您在编辑事件详细信息后按下后退/向上时,与默认日历应用程序的行为相同)
我目前的方法(未经测试)如下:
对于“向上”导航,我覆盖了片段上的onOptionsItemSelected
:
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)
}
对于“返回”导航,我在片段和它的Activity之间创建了一个自定义接口和回调系统:
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
}
}
...
}
对于这么简单的事情来说,这一切都是相当恶心和样板的。有没有更好的方法?
6条答案
按热度按时间cngwdvgl1#
从
androidx.appcompat:appcompat:1.1.0-beta01
开始,为了拦截带有导航组件的后退按钮,您需要向OnBackPressedDispatcher
添加回调。此回调必须扩展OnBackPressedCallback
并覆盖handleOnBackPressed
。OnBackPressedDispatcher
遵循责任链模式来处理回调。换句话说,如果您将回调设置为enabled,则仅执行您的回调。否则,OnBackPressedDispatcher
将忽略它并继续执行下一个回调,以此类推,直到找到一个已启用的回调(例如,当您有多个回调时,这可能会很有用)。因此,为了显示对话框,你必须在Fragment中执行类似的操作:
addCallback
方法接收一个LifecycleOwner
,并且它将确保在LifecycleOwner
到达STARTED
阶段时添加回调,不仅如此,这还使得当其关联的LifecycleOwner
被销毁时删除回调。至于up按钮,似乎(至少现在)没有太多的可能性。到目前为止,我能找到的使用导航组件的唯一选项是为导航本身添加一个侦听器,它将同时处理两个按钮:
无论如何,这都有一个警告,即允许您添加侦听器的活动或片段知道它可能不应该知道的目的地。
inb24sb22#
使用导航体系结构组件,您可以执行以下操作:
1.告诉你的活动把所有点击主页按钮(后退箭头)的点击发送给所有正在收听它的人。
1.然后在你的片段中,像这样消耗事件
iovurdzv3#
对于向上导航,只需覆盖onOptionsItemSelected()
stszievb4#
您可以在片段中的
onAttach
中使用以下函数,以便在导航组件的帮助下覆盖onBackPressed()
。6xfqseft5#
如果您将其与AppBarConfiguration一起使用,则最新版本中现在提供了AppBarConfiguration.OnNavigateUpListener。有关详细信息,请参阅以下链接
https://developer.android.com/reference/androidx/navigation/ui/AppBarConfiguration.OnNavigateUpListener
gcuhipw96#
如果您在活动中覆盖onBackPressed(),则必须确保它应该调用super.onBackOnBackPressed(),否则这些调度程序不会触发