问题
I have the following Activity
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()
}
}
which as you can see is associated with navigation graph, and I am using a navigation drawer. When I am navigating through the items in the drawer I want to keep the hamburger icon, and only change it to up/back button when I click on an item within the fragment or popup for example and ensure that the behavior of the system reflects what the user expects based on the icon displayed. Is that possible
回答1:
To control when the AppBar navigation up/back show the following need to be done
1- create AppBarConfiguration and pass to it the top level destination and drawerLayout
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.dest_one,
R.id.dest_two
),
drawerLayout
)
2- Tell the AppBar about the configration and navigation. this will help to show a title and show up arrow or drawer menu icon
setupActionBarWithNavController(navController, appBarConfig)
3- Finally override the onOptionsItemSelected and onSupportNavigateUp and the Navigation Component extension to inform the AppBar how to behave
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)
Reference Google Code Lab Navigation Navigation Codelab
回答2:
Follow this steps
1. Bind your NavigationView with NavigationUI
NavigationUI.setupWithNavController(nav_view, hostFragment.navController)
2. Bind ActionBar With NavController
NavigationUI.setupActionBarWithNavController(this@NavActivity, hostFragment.navController)
3. Bind ActionBar and DrawerLayout With NavController
NavigationUI.setupActionBarWithNavController(this@NavActivity, hostFragment.navController, drawer_layout)
4. override onSupportNavigateUp()
in your activity
override fun onSupportNavigateUp(): Boolean {
return NavigationUI.navigateUp(drawer_layout, hostFragment.navController)
|| super.onSupportNavigateUp()
}
Sample:
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
}
}
Output
Home Fragment:
Fragment Two:
Fragment Tree:
回答3:
So, I think that you can use the NavController.OnNavigatedListener to listen wich fragment will be shown, and then update de toolbar icon.
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
}
})
Sorry, I have no computer here, so I write this code without any IDE, this can have error. But take the idea.
Hope this help you.
来源:https://stackoverflow.com/questions/52172111/navigation-component-control-when-to-show-hamburger-or-back-icon