导航组件,控制何时显示汉堡包或返回图标

Posted

技术标签:

【中文标题】导航组件,控制何时显示汉堡包或返回图标【英文标题】:Navigation Component, Control when to show hamburger or back icon 【发布时间】:2019-02-09 19:56:14 【问题描述】:

我有以下活动

class MainActivity : AppCompatActivity() 

private lateinit var drawerLayout: androidx.drawerlayout.widget.DrawerLayout

override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_activity)

    drawerLayout = drawer_layout

    val navController = Navigation.findNavController(this, R.id.fragment_main_navHost)

    setSupportActionBar(toolbar)

    NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)
    navView_main.setupWithNavController(navController)


override fun onSupportNavigateUp(): Boolean 
    return NavigationUI.navigateUp(drawerLayout,
        Navigation.findNavController(this, R.id.fragment_main_navHost))


override fun onBackPressed() 
    if (drawerLayout.isDrawerOpen(GravityCompat.START)) 
        drawerLayout.closeDrawer(GravityCompat.START)
     else 
        super.onBackPressed()
    

您可以看到它与导航图相关联,我正在使用导航抽屉。当我浏览抽屉中的项目时,我想保留汉堡图标,并且仅在单击片段或弹出窗口中的项目时将其更改为上/后退按钮,并确保系统的行为反映了什么用户期望基于显示的图标。有可能吗

【问题讨论】:

【参考方案1】:

要控制AppBar导航上/后显示的时间需要做以下操作

1- 创建 AppBarConfiguration 并将***目的地和抽屉布局传递给它

    appBarConfiguration = AppBarConfiguration(
        setOf(
            R.id.dest_one,
            R.id.dest_two
        ),
        drawerLayout
    )

2- 告诉 AppBar 配置和导航。这将有助于显示标题并显示向上箭头或抽屉菜单图标

setupActionBarWithNavController(navController, appBarConfig)

3- 最后覆盖 onOptionsItemSelected 和 onSupportNavigateUp 以及导航组件扩展,以告知 AppBar 的行为方式

    override fun onOptionsItemSelected(item: MenuItem)= item.onNavDestinationSelected(findNavController(R.id.my_nav_host_fragment))
        || super.onOptionsItemSelected(item)


override fun onSupportNavigateUp() = findNavController(R.id.my_nav_host_fragment).navigateUp(appBarConfiguration)

参考谷歌代码实验室导航Navigation Codelab

【讨论】:

我尝试了这段代码并定义了我所有的***目的地,但是当我从***目的地移动到另一个片段时,显示返回按钮,当单击工具栏的返回按钮时,抽屉将再次打开.我该如何解决这个问题 能否请您分享代码 sn-p 或其他东西,看看您在做什么 能否分享到github并提供链接 其实我可以将它作为另一个问题提出并分享链接。可以吗? ***.com/questions/56219768/…【参考方案2】:

按照这些步骤进行

1.绑定你的NavigationView with NavigationUI

NavigationUI.setupWithNavController(nav_view, hostFragment.navController)

2.绑定ActionBar With NavController

NavigationUI.setupActionBarWithNavController(this@NavActivity, hostFragment.navController)

3.绑定ActionBar and DrawerLayout With NavController

NavigationUI.setupActionBarWithNavController(this@NavActivity, hostFragment.navController, drawer_layout)

4. 在您的活动中覆盖 onSupportNavigateUp()

override fun onSupportNavigateUp(): Boolean 
    return NavigationUI.navigateUp(drawer_layout, hostFragment.navController) 
              || super.onSupportNavigateUp()

示例:

class NavActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener 

    lateinit var hostFragment: NavHostFragment

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_nav)
        setSupportActionBar(toolbar)

        fab.setOnClickListener  view ->
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show()
        

        val toggle = ActionBarDrawerToggle(
                this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
        drawer_layout.addDrawerListener(toggle)
        toggle.syncState()

        nav_view.setNavigationItemSelectedListener(this)

        hostFragment = supportFragmentManager.findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment    
        NavigationUI.setupWithNavController(nav_view, hostFragment.navController)    
        NavigationUI.setupActionBarWithNavController(this@NavActivity, hostFragment.navController)    
        NavigationUI.setupActionBarWithNavController(this@NavActivity, hostFragment.navController, drawer_layout)    
    

    override fun onBackPressed() 
        if (drawer_layout.isDrawerOpen(GravityCompat.START)) 
            drawer_layout.closeDrawer(GravityCompat.START)
         else 
            super.onBackPressed()
        
    

    override fun onSupportNavigateUp(): Boolean 
        return NavigationUI.navigateUp(drawer_layout, hostFragment.navController) || super.onSupportNavigateUp()
    

    override fun onCreateOptionsMenu(menu: Menu): Boolean 
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.nav, menu)
        return true
    

    override fun onOptionsItemSelected(item: MenuItem): Boolean 
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        when (item.itemId) 
            R.id.action_settings -> return true
            else -> return super.onOptionsItemSelected(item)
        
    

    override fun onNavigationItemSelected(item: MenuItem): Boolean 
        // Handle navigation view item clicks here.
        drawer_layout.closeDrawer(GravityCompat.START)
        return true
    


输出

首页片段:

片段二:

片段树:

【讨论】:

感谢您的尝试,但是您提供的步骤不是必需的,并且产生了相同的结果。使用导航抽屉导航时,我应该能够控制要显示的图标。 原则上,抽屉导航应该有横向导航,这意味着项目处于同一级别。因此,当我使用抽屉从一个项目移动到另一个项目时,应该替换片段而不是添加到堆栈顶部。请参阅material.io/design/navigation/…。最后一件事,你只需要第三步,如果你想让拱形组件控制后退行为,第四步 当我点击后退箭头时,它会显示导航抽屉而不是返回到上一个片段。 @AVEbrahimi hasu override onSupportNavigateUp() 方法就像我上面的代码 当我点击后退箭头时,它会显示导航抽屉而不是返回到上一个片段。 – 有什么解决方案吗,我不是在寻找解决方法【参考方案3】:

所以,我认为您可以使用 NavController.OnNavigatedListener 来监听将显示的片段,然后更新工具栏图标。

val navController = Navigation.findNavController(this, R.id.fragment_main_navHost)
navController.addOnNavigatedListener(contoller, destination -> 
   if(destination.id == R.id.fragmentTwo)
          // change the toolbar icon here

    )

对不起,我这里没有电脑,所以我在没有任何 IDE 的情况下编写此代码,这可能会出错。但请接受这个想法。

希望对您有所帮助。

【讨论】:

虽然您的回答可能是一种解决方法,但我希望有一个解决方案可以自动执行此过程。这将需要跟踪片段以了解要执行的操作。这样,我将失去 Navigation Arch 组件的好处。

以上是关于导航组件,控制何时显示汉堡包或返回图标的主要内容,如果未能解决你的问题,请参考以下文章

安卓导航组件。显示带有从箭头到十字的变形导航图标的全屏对话框

何时使用汉堡包菜单设计

工具栏导航汉堡图标丢失

使用带有喷气背包导航组件的导航抽屉时如何更改工具栏图标(汉堡图标)

获取 Toolbar 的导航图标视图参考

Android 导航图标 - 个人资料图片而不是汉堡包图标