通常,我在代码A中使用val navController: NavController = findNavController(R.id.nav_host_fragment)
查找NavController,它是基于R.id.nav_host_fragment
的。
现在我在应用程序中使用视图绑定,就像代码B一样,如果我使用视图绑定,我如何使用NavController?
顺便说一句,在我看来,R.id.nav_host_fragment
在视图绑定中是不可用的,对吗?
码A
class TasksActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.tasks_act)
val navController: NavController = findNavController(R.id.nav_host_fragment)
}
}
码B
class TasksActivity : AppCompatActivity() {
private lateinit var binding: TasksActBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = TasksActBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
//val navController: NavController = findNavController(R.id.nav_host_fragment)
}
}
tasks_act.xml
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".tasks.TasksActivity"
tools:openDrawer="start">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="@style/Toolbar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</com.google.android.material.appbar.AppBarLayout>
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
</LinearLayout>
..
</androidx.drawerlayout.widget.DrawerLayout>
发布于 2020-07-12 10:09:08
我们使用ViewBinding获取视图本身的引用。如果在TextView中使用视图绑定,则将获得视图的引用。
在findNavController的情况下,如果使用Viewbinding,您将得到对片段的引用,而NavCotroller则期望整数类型的ViewId。
findNavController(@IdRes viewId: int)
发布于 2020-07-25 18:24:47
代码B应该还能正常工作。
我看了一下findNavController()
。这是一个简化代码的扩展函数,扩展函数的代码是
fun Activity.findNavController(@IdRes viewId: Int): NavController =
Navigation.findNavController(this, viewId)
现在查看findNavController()
在Navigation
中的代码,我们在下面看到
@NonNull
public static NavController findNavController(@NonNull Activity activity, @IdRes int viewId) {
View view = ActivityCompat.requireViewById(activity, viewId);
NavController navController = findViewNavController(view);
if (navController == null) {
throw new IllegalStateException("Activity " + activity
+ " does not have a NavController set on " + viewId);
}
return navController;
}
我们传递给参数的viewId在第一行中使用。
View view = ActivityCompat.requireViewById(activity, viewId);
现在查看requireViewById()
内部的ActivityCompat
,我们看到
@NonNull
public static <T extends View> T requireViewById(@NonNull Activity activity, @IdRes int id) {
if (Build.VERSION.SDK_INT >= 28) {
return activity.requireViewById(id);
}
T view = activity.findViewById(id);
if (view == null) {
throw new IllegalArgumentException("ID does not reference a View inside this Activity");
}
return view;
}
对于api 28,并加上调用的方法是
@NonNull
public final <T extends View> T requireViewById(@IdRes int id) {
T view = findViewById(id);
if (view == null) {
throw new IllegalArgumentException("ID does not reference a View inside this Activity");
}
return view;
}
因此,只要将视图(其中包含nav_host_fragment
)附加到活动中,您为查找nav控制器而编写的代码就应该可以完全正常工作。
class TasksActivity : AppCompatActivity() {
private lateinit var binding: TasksActBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = TasksActBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view) //you are attaching view to activity here , make sure you always call this before the next line , else you will get IllegalStateException
val navController: NavController = findNavController(R.id.nav_host_fragment)
}
}
我没有亲自测试过代码,但据我所见,它应该工作得很好。
发布于 2021-05-28 15:47:33
正确的工作方式如下:
必须从FragmentContainerView访问supportFragmentManager:
val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragment) as NavHostFragment
val navController = navHostFragment.navController
https://stackoverflow.com/questions/62858335
复制相似问题