【问题标题】:Navigation with View Binding使用视图绑定导航
【发布时间】:2020-03-18 03:50:17
【问题描述】:

我正在尝试使用视图绑定替换所有 findViewById。但是,我无法使用 View Binding 更改我的 NavController 代码行。

val navController = findNavController(this, R.id.mainHostFragment)

var binding : ActivityMainBinding
val navController = findNavController(this, binding.mainHostFragment)

我该怎么做?

【问题讨论】:

    标签: android-navigation android-viewbinding


    【解决方案1】:

    您不能将其替换为视图绑定。 findNavController 不仅仅是在布局中查找视图。

    看看源码here

    /**
    * Find a {@link NavController} given a local {@link Fragment}.
    *
    * <p>This method will locate the {@link NavController} associated with this Fragment,
    * looking first for a {@link NavHostFragment} along the given Fragment's parent chain.
    * If a {@link NavController} is not found, this method will look for one along this
    * Fragment's {@link Fragment#getView() view hierarchy} as specified by
    * {@link Navigation#findNavController(View)}.</p>
    *
    * @param fragment the locally scoped Fragment for navigation
    * @return the locally scoped {@link NavController} for navigating from this {@link Fragment}
    * @throws IllegalStateException if the given Fragment does not correspond with a
    * {@link NavHost} or is not within a NavHost.
    */
    @NonNull
    public static NavController findNavController(@NonNull Fragment fragment) {
    Fragment findFragment = fragment;
    while (findFragment != null) {
        if (findFragment instanceof NavHostFragment) {
            return ((NavHostFragment) findFragment).getNavController();
        }
        Fragment primaryNavFragment = findFragment.getParentFragmentManager()
                .getPrimaryNavigationFragment();
        if (primaryNavFragment instanceof NavHostFragment) {
            return ((NavHostFragment) primaryNavFragment).getNavController();
        }
        findFragment = findFragment.getParentFragment();
    }
    // Try looking for one associated with the view instead, if applicable
    View view = fragment.getView();
    if (view != null) {
        return Navigation.findNavController(view);
    }
    throw new IllegalStateException("Fragment " + fragment
            + " does not have a NavController set");
    }
    

    它不仅仅是找到控制器。它遍历、创建片段、创建视图并抛出异常。

    视图绑定只是生成一个绑定类,其中包含您布局的所有视图。它不是用来查找应用的导航控制器的。

    【讨论】:

      【解决方案2】:

      answer 的帮助下,我找到了一个简单的实现

      binding?.apply {
              setContentView(root)
              setSupportActionBar(toolbar)
              navController = (supportFragmentManager
                  .findFragmentById(fragmentHost.id) as NavHostFragment)
                  .navController
              setupActionBarWithNavController(navController, appBarConfiguration)
              bottom.setupWithNavController(navController)
          }
      

      【讨论】:

      • 出色但更少的代码“nav= ...”可以在“nav= this.findNavController(R.id.myNavHostFragment)”上更改
      • 这个解决方案是否有创建两次树的开销?
      • @Fortran 是的,这是一个棘手的答案,因为您正在应用绑定,但您再次使用 R.id 强制引用所有小部件...
      【解决方案3】:

      findNavController(R.id.nav_host_fragment) 应该在将视图附加到这样的活动之后:

      setContentView(binding.root)
      val navController: NavController = findNavController(R.id.nav_host_fragment) 
      

      更多Here

      【讨论】:

        【解决方案4】:

        这是我的示例代码,使用视图绑定和导航。

        import android.os.Bundle
        import androidx.appcompat.app.AppCompatActivity
        import androidx.navigation.fragment.NavHostFragment
        import androidx.navigation.ui.AppBarConfiguration
        import androidx.navigation.ui.setupActionBarWithNavController
        import androidx.navigation.ui.setupWithNavController
        import com.zeddigital.zigmaster.databinding.ActivityMainBinding
        
        
        class MainActivity : AppCompatActivity() {
        
            private lateinit var appBarConfiguration: AppBarConfiguration
            private lateinit var binding : ActivityMainBinding
        
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
        
                /*
                Use view binding in activities
                
                Call the static inflate() method included in the generated binding class. 
                This creates an instance of the binding class for the activity to use.
                Get a reference to the root view by either calling the getRoot() method or using Kotlin property syntax.
                Pass the root view to setContentView() to make it the active view on the screen.*/
                binding = ActivityMainBinding.inflate(layoutInflater)
        
                val view = binding.root
                setContentView(view)
        
                setSupportActionBar(binding.appBarMain.toolbar)
        
                //val navController = findNavController(R.id.nav_host_fragment)
                val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
                val navController = navHostFragment.navController
        
                // Passing each menu ID as a set of Ids because each
                // menu should be considered as top level destinations.
                appBarConfiguration = AppBarConfiguration(setOf(
                        R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow), binding.drawerLayout)
                setupActionBarWithNavController(navController, appBarConfiguration)
                binding.navView.setupWithNavController(navController)
        
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2021-10-19
          • 1970-01-01
          • 2023-04-07
          • 1970-01-01
          • 2023-04-02
          • 2012-01-16
          • 1970-01-01
          • 1970-01-01
          • 2010-10-23
          相关资源
          最近更新 更多