首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如果我使用视图绑定,如何找到NavController?

如果我使用视图绑定,如何找到NavController?
EN

Stack Overflow用户
提问于 2020-07-12 07:31:44
回答 3查看 4.9K关注 0票数 5

通常,我在代码A中使用val navController: NavController = findNavController(R.id.nav_host_fragment)查找NavController,它是基于R.id.nav_host_fragment的。

现在我在应用程序中使用视图绑定,就像代码B一样,如果我使用视图绑定,我如何使用NavController?

顺便说一句,在我看来,R.id.nav_host_fragment在视图绑定中是不可用的,对吗?

码A

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
<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>
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-07-12 10:09:08

我们使用ViewBinding获取视图本身的引用。如果在TextView中使用视图绑定,则将获得视图的引用。

findNavController的情况下,如果使用Viewbinding,您将得到对片段的引用,而NavCotroller则期望整数类型的ViewId。

代码语言:javascript
运行
复制
findNavController(@IdRes viewId: int)
票数 2
EN

Stack Overflow用户

发布于 2020-07-25 18:24:47

代码B应该还能正常工作。

我看了一下findNavController()。这是一个简化代码的扩展函数,扩展函数的代码是

代码语言:javascript
运行
复制
fun Activity.findNavController(@IdRes viewId: Int): NavController =
    Navigation.findNavController(this, viewId)

现在查看findNavController()Navigation中的代码,我们在下面看到

代码语言:javascript
运行
复制
 @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在第一行中使用。

代码语言:javascript
运行
复制
View view = ActivityCompat.requireViewById(activity, viewId);

现在查看requireViewById()内部的ActivityCompat,我们看到

代码语言:javascript
运行
复制
  @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,并加上调用的方法是

代码语言:javascript
运行
复制
@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控制器而编写的代码就应该可以完全正常工作。

代码语言:javascript
运行
复制
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)       
    }

}

我没有亲自测试过代码,但据我所见,它应该工作得很好。

票数 4
EN

Stack Overflow用户

发布于 2021-05-28 15:47:33

正确的工作方式如下:

必须从FragmentContainerView访问supportFragmentManager:

代码语言:javascript
运行
复制
val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragment) as NavHostFragment

val navController = navHostFragment.navController
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62858335

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档