【问题标题】:Kotlin navigate with fragment name not idKotlin 使用片段名称而不是 id 导航
【发布时间】:2021-04-22 02:21:42
【问题描述】:

如果我使用类似 navController.navigate(R.id.action_nav_home_to_profileFragment) 的东西,它会导航到目标片段(从我的主片段),因为它在 mainFragment 导航文件中有操作,但如果我在其他片段中,它不会导航,因为它没有这些片段中没有动作。

我的问题是:是否可以在不使用操作 ID 的情况下从任何片段导航到我的目标片段?而是使用片段名称?

PS:这个按钮位于我的顶部栏中,这就是为什么我需要它能够从任何片段导航到目标片段。

代码

navigation

<fragment
    android:id="@+id/nav_home"
    android:name="irando.co.id.kerjaremote.ui.home.HomeFragment"
    android:label="@string/menu_home"
    tools:layout="@layout/fragment_home" >
    <argument android:name="projectSlugArgument" />
    <action
        android:id="@+id/action_nav_home_to_projectDetailsFragment"
        app:destination="@id/projectDetailsFragment" />
    <argument android:name="searchArgument" />
    <action
        android:id="@+id/action_nav_home_to_searchFragment"
        app:destination="@id/searchFragment" />



    <!--  destination action (works only when I'm in main fragment) -->
    <action
        android:id="@+id/action_nav_home_to_profileFragment"
        app:destination="@id/profileFragment" />
</fragment>

<!-- destination fragment -->
<fragment
    android:id="@+id/profileFragment"
    android:name="irando.co.id.kerjaremote.ui.auth.ProfileFragment"
    android:label="fragment_profile"
    tools:layout="@layout/fragment_profile" />

mainActivity

override fun onOptionsItemSelected(item: MenuItem): Boolean {
  // Handle presses on the action bar menu items
  when (item.itemId) {
    R.id.action_profile -> {
      navController.navigate(R.id.action_nav_home_to_profileFragment)
    }
  }
  return super.onOptionsItemSelected(item)
}

更新

我的导航是如何工作的:

我正在从加载片段的 MainActivity 进行此导航。

MainActivity.kt

class MainActivity : AppCompatActivity() {

    lateinit var sesssion: SessionManager
    lateinit var navController: NavController // <--------------------- here
    private lateinit var appBarConfiguration: AppBarConfiguration

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val toolbar: Toolbar = findViewById(R.id.toolbar)
        setSupportActionBar(toolbar)

        val fab: FloatingActionButton = findViewById(R.id.fab)
        fab.setOnClickListener { view ->
            val intent = Intent(this, PublishActivity::class.java)
            startActivity(intent)
        }

        val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
        navController = navHostFragment.navController // <--------------------- here

        val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
        val navView: NavigationView = findViewById(R.id.nav_view)
        // 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_my_projects, R.id.nav_my_bids, R.id.nav_slideshow
            ), drawerLayout
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
        navView.setupWithNavController(navController)
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.main, menu)
        val action_auth = menu.findItem(R.id.action_auth)
        val action_profile = menu.findItem(R.id.action_profile)
        sesssion = SessionManager(this)

        if (sesssion.isLoggedIn()) {
            action_auth.isVisible = false
            action_profile.isVisible = true
        } else {
            action_auth.isVisible = true
            action_profile.isVisible = false
        }
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        // Handle presses on the action bar menu items
        when (item.itemId) {
            R.id.action_auth -> {
                val i = Intent(this, AuthActivity::class.java)
                startActivity(i)
                return true
            }
            R.id.action_profile -> {
                navController.navigate(R.id.action_nav_to_profileFragment) // <--------------------- here (global action)
            }
        }
        return super.onOptionsItemSelected(item)
    }

    override fun onSupportNavigateUp(): Boolean {
        navController = findNavController(R.id.nav_host_fragment) // <--------------------- here
        return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
    }

    // ability of setting top bar title in fragments
    fun setActionBarTitle(title: String?) {
        supportActionBar!!.title = title
    }
}

xml

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <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" />
</androidx.drawerlayout.widget.DrawerLayout>

【问题讨论】:

    标签: android kotlin android-fragments android-navigation


    【解决方案1】:

    是的,你可以。 你有两个选择。

    1> 创建一个全局动作。在此链接中查看更多信息:https://developer.android.com/guide/navigation/navigation-global-action

    2> 按片段的 id 导航。示例:

       android:id="@+id/profileFragment"
    

    navController.navigate(R.id.profileFragment)

    【讨论】:

    • 我只是在尝试navController.navigate(R.id.profileFragment) 它确实适用于大多数片段,但在某些片段中它不起作用(不知道为什么)
    • 在我的一些片段中,这是它给出的错误Ignoring navigate() call: FragmentManager has already saved its state
    【解决方案2】:

    是否可以在不使用操作 ID 的情况下从任何片段导航到我的目标片段?而是使用片段名称?

    不,你不能使用片段名称,但片段 ID

    您还可以使用全局操作,允许您从任何片段转到特定的目标片段。

    这可以使用直接在&lt;navigation&gt; 标签下的&lt;action&gt; 标签来完成

    <navigation ....>
    
        <fragment
            android:id="@+id/..."
    
        <action
            android:id="@+id/action_global_profileFragment"
            app:destination="@id/profileFragment" />
    
    </navigation>
    

    【讨论】:

    • 是的,我现在正在尝试全球行动,上面写着Ignoring navigate() call: FragmentManager has already saved its state
    • 你是否在同一个 navGraph 中从一个片段移动到另一个片段,你能否更新一下你是如何做到这一点的
    • 你能不能在optionsItemSelectiedR.id.action_profile的情况下return true,还要确保全局动作action_nav_to_profileFragment直接在&lt;navigation&gt;下,而不是在任何其他片段下
    • 我已经完成了所有这些但错误是相同的,在某些片段中我得到Ignoring navigate() call: FragmentManager has already saved its state,当我尝试打开抽屉应用程序时出现以下错误MainActivity@ff61d9b does not have a NavController set on 2131362110来自@ 987654332@ 现在我不确定哪个错误是正确的:D
    • 请让我彻底检查一下
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    • 2021-08-06
    • 2020-10-04
    • 2019-03-13
    • 1970-01-01
    • 1970-01-01
    • 2019-10-02
    相关资源
    最近更新 更多