这听起来像你想实现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 开发人员指南链接。