问题
I am using the new Navigation component from Android Jetpack.
The root Activity setup is quite simple:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
val navController = findNavController(R.id.navigationFragment)
setupActionBarWithNavController(navController)
bottomNavigationView.setupWithNavController(navController)
}
It works well when the Fragment's title is defined in the navigation graph. But for one Fragment, I want to set the title dynamically.
I tried with findNavController().currentDestination.label = "Hello world"
but it does nothing.
I could of course use a trick like (activity as? AppCompatActivity)?.supportActionBar?.title = "Hello world"
, but I feel that it will break the magic that setupActionBarWithNavController()
does for me. It there any way to update the Action Bar title dynamically?
回答1:
As of 1.0.0-alpha08
, you can have the NavigationUI bits dynamically set the title... if the dynamic bits are arguments on the navigation action.
So, for example, in your navigation graph, you could have something like this:
<fragment
android:id="@+id/displayFragment"
android:name="com.commonsware.jetpack.sampler.nav.DisplayFragment"
android:label="Title: {title}" >
<argument
android:name="modelId"
app:argType="string" />
<argument
android:name="title"
app:argType="string" />
</fragment>
Here, the android:label
attribute for our <fragment>
has an argument name wrapped in braces ({title}
in "Title: {title}"
. The app bar's title will then be set to the value of the label, with {title}
replaced by the value of the title
argument.
If you need something more elaborate than that — for example, you want to look up the model by ID and read a property from it — you will need to use more manual approaches, such as those outlined in other answers to this question.
回答2:
As of now, The Jetpack Navigation Architecture components do not provide any "built in" way to do this, and you'll have to implement your own "custom" method for doing it.
There is an existing feature request to get functionality for dynamic labels on destinations added to the new Jetpack Navigation Architecture Components. If you are here because you want/need this functionality, please star the existing feature request, here: https://issuetracker.google.com/issues/80267266
回答3:
Taking consideration that your host activity is MainActivity
, just add the following code to your MainActivity
's onCreate
fun
val navController = Navigation.findNavController(this, R.id.nav_host_fragment)
// setting title according to fragment
navController.addOnDestinationChangedListener {
controller, destination, arguments ->
toolbar.title = navController.currentDestination?.label
}
回答4:
Remove label from graph.xml file
android:label="fragment_info"
and use old school approach if you want to set title of the fragment dynamically from the fragment itself
getActivity().setTitle("Your Title");
回答5:
Another solution is to use ViewModel and LiveData, attach viewmodel to your activity and fragments, add a livedata field inside viewmodel
val title = MutableLiveData<String>()
From your activity observe this field, and if it is changed update the toolbar title
viewModel?.title?.observe(this, Observer {
my_toolbar.title=it
})
From your desired fragment change the title field inside the viewmodel
viewModel?.title?.value="New title"
回答6:
Well, now the Navigation UI supports this feature. Now the ActionBar
title changes dynamically. You just have to setup the ActionBar
with the NavController
.
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
preferedTheme()
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
navController = findNavController(R.id.nav_controller_fragment)
appBarConfiguration = AppBarConfiguration(navController.graph)
setupActionBarWithNavController(navController, appBarConfiguration)
}
And set action bar label in nav graph:
<navigation 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/mobile_navigation"
app:startDestination="@id/mainFragment">
<fragment android:id="@+id/mainFragment"
android:name="com.cinderellaman.general.ui.fragments.MainFragment"
android:label="General"
tools:layout="@layout/main_fragment"/>
And now its also support Navigate Up:
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
回答7:
Until the issue will be fixed, simple listener is working to me:
/**
* Temporary solution to dynamically change title of actionbar controlled by Navigation component
* Should be removed as soon as the bug on Navigation will be fixed: (https://issuetracker.google.com/issues/80267266)
*/
interface TempToolbarTitleListener {
fun updateTitle(title: String)
}
class MainActivity : AppCompatActivity(), TempToolbarTitleListener {
...
override fun updateTitle(title: String) {
binding.toolbar.title = title
}
}
change title from fragment:
(activity as TempToolbarTitleListener).updateTitle("custom title")
回答8:
If you use toolbar on setSupportActionBar in Activity and you would like to change its title in frgament, then below code may gonna help you ;)
(requireActivity() as MainActivity).toolbar.title = "Title here"
回答9:
On trying the activity's title it seems to override the title for fragment. Being on safe side you must put on onResume
.
override fun onResume() {
super.onResume()
activity?.toolbar.title = "YOUR_TITLE_HERE"
}
it works for me !
Note : Must have Toolbar Widget in activity
Add toolbar like this in your activity's xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"">
<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" />
</com.google.android.material.appbar.AppBarLayout>
<!-- Other Widgets -->
</androidx.coordinatorlayout.widget.CoordinatorLayout>
回答10:
you can remove android:label in navigation graph then write in onCreateView()
activity?.title="your title"
回答11:
You can add addOnNavigatedListener inside your activity, and based on current destination change the title
findNavController(nav_host_fragment).addOnNavigatedListener { controller, destination ->
when(destination.id) {
R.id.destination1 -> {
my_toolbar.title= "Some title"
}
R.id.destination2 -> {
my_toolbar.title= "Othertitle"
}
}
}
来源:https://stackoverflow.com/questions/50599238/dynamic-actionbar-title-from-a-fragment-using-androidx-navigation