我已经为应用程序使用了默认的Android Studio 3.5“导航抽屉”模板。该模板使用“新”(?)NavigationController在导航抽屉中的一组示例片段之间进行导航。
虽然我非常喜欢它的工作方式,但是我正在寻找一种方法,以防止在当前片段很脏的情况下导航到另一个片段(例如:包含未保存的更改)。到目前为止,我还无法弄清楚如何进行这项工作。似乎没有任何事件可让我取消导航。
我还试图在模板生成的以下代码中添加另一行:
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
这将在片段之间建立基本导航。现在,当我添加以下行时:
navView.setNavigationItemSelectedListener(this)
当确实选择了另一个项目时,我确实会收到通知,但这完全禁用了导航,因为先前由navView.setupWithNavController(navController)
设置的监听器已由this
替换。
所以也许有人可以启发我是否有某种方法可以在某些条件下取消这种导航,而不必自己执行片段导航?
PS:在旁注中,我还需要导航抽屉中的两个项目才能实际打开单独的活动,这与Google传播的“单个活动”模式相抵触,但在我的情况下实际上是必需的。当然,删除我在上面添加的行会导致无法对导航抽屉中的其他项目做出预期的反应。
也许整个方法都不适合我的情况?
答案 0 :(得分:1)
听起来您想实现Conditional Navigation。
也就是说,要实现您的要求,您可以扩展NavigationView
以包括首先触发的“预览”侦听器(Kotlin语法):
package com.example.myapp
import android.content.Context
import android.util.AttributeSet
import android.view.MenuItem
import com.google.android.material.navigation.NavigationView
class CancellableNavigationView(context: Context, attrs: AttributeSet) :
NavigationView(context, attrs) {
private var cancellableListener =
object : OnNavigationItemSelectedListener {
var listener: OnNavigationItemSelectedListener? = null
var prevListener: OnNavigationItemSelectedListener? = null
override fun onNavigationItemSelected(item: MenuItem): Boolean {
if (listener?.onNavigationItemSelected(item) == false) {
return false
}
return prevListener?.onNavigationItemSelected(item) ?: true
}
}
override fun setNavigationItemSelectedListener(
listener: OnNavigationItemSelectedListener?
) {
cancellableListener.prevListener = listener
super.setNavigationItemSelectedListener(cancellableListener)
}
fun setNavigationItemSelectedPreviewListener(
listener: OnNavigationItemSelectedListener?
) {
cancellableListener.listener = listener
}
}
要使用此功能,请在您的活动布局中替换
...
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" />
...
使用新类,并保留以下属性:
...
<com.example.myapp.CancellableNavigationView
android:id="@+id/nav_view"
... />
...
然后,在您的活动中,您可以使用新的预览侦听器有条件地取消导航:
...
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
fun changesNeedSaving() : Boolean { ... }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
appBarConfiguration = AppBarConfiguration(TOP_LEVEL_NAV, drawer_layout)
setupActionBarWithNavController(nc, appBarConfiguration)
nav_view.setupWithNavController(nc)
nav_view.setNavigationItemSelectedPreviewListener(
NavigationView.OnNavigationItemSelectedListener { item ->
Log.d(TAG, "got item: $item")
!changesNeedSaving() // Conditionally allow navigation
})
...
}
...
}
注意:仅适用于抽屉的NavigationView
部分,它不会让您取消NavController
触发的导航。为此,请参阅此答案顶部的“ Android开发人员指南”链接。