J'utilise le nouveau composant Navigation de Android Jetpack.
La configuration de l'activité racine est assez 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)
}
Cela fonctionne bien lorsque le titre du fragment est défini dans le graphe de navigation. Mais pour un fragment, je veux définir le titre dynamiquement.
J'ai essayé avec findNavController().currentDestination.label = "Hello world"
mais cela ne fait rien.
Je pourrais bien sûr utiliser un truc du genre (activity as? AppCompatActivity)?.supportActionBar?.title = "Hello world"
, Mais j’ai l’impression que cela brisera la magie que setupActionBarWithNavController()
fait pour moi. Y at-il un moyen de mettre à jour le titre de la barre d’action de manière dynamique?
À partir de 1.0.0-alpha08
, vous pouvez faire en sorte que les bits NavigationUI définissent le titre de manière dynamique ... si les bits dynamiques sont des arguments de l'action de navigation.
Ainsi, par exemple, dans votre graphique de navigation, vous pourriez avoir quelque chose comme ceci:
<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>
Ici le Android:label
attribut pour notre <fragment>
a un nom d’argument entouré d’accolades ({title}
dans "Title: {title}"
. Le titre de la barre d'application sera alors défini sur la valeur de l'étiquette, avec {title}
remplacé par la valeur de l'argument title
.
Si vous avez besoin de quelque chose de plus élaboré que cela (par exemple, si vous souhaitez rechercher le modèle par ID et en lire une propriété), vous devrez utiliser des méthodes plus manuelles, telles que celles décrites dans d'autres réponses à cette question.
Pour le moment, les composants de l'architecture de navigation de Jetpack ne fournissent aucun moyen "intégré" de le faire, et vous devrez implémenter votre propre méthode "personnalisée" pour le faire.
Il existe une demande de fonctionnalité existante pour obtenir une fonctionnalité pour les étiquettes dynamiques sur les destinations ajoutées aux nouveaux composants de l'architecture de navigation de Jetpack. Si vous êtes ici parce que vous souhaitez/avez besoin de cette fonctionnalité, veuillez indiquer la demande de fonctionnalité existante, ici: https://issuetracker.google.com/issues/80267266
Si vous considérez que votre activité hôte est MainActivity
, ajoutez simplement le code suivant à votre MainActivity
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
}
Eh bien, maintenant, l'interface de navigation prend en charge cette fonctionnalité. Maintenant, le titre ActionBar
change dynamiquement. Vous devez juste configurer le ActionBar
avec le 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)
}
Et définissez le libellé de la barre d’action dans le graphique de navigation:
<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"/>
Et maintenant, il supporte également Naviguer vers le haut:
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
Supprimer l'étiquette du fichier graph.xml
Android:label="fragment_info"
et utilisez l'approche old school si vous souhaitez définir le titre du fragment de manière dynamique à partir du fragment lui-même.
getActivity().setTitle("Your Title");
Une autre solution consiste à utiliser ViewModel et LiveData, associez viewmodel à votre activité et à vos fragments, et ajoutez un champ
val title = MutableLiveData<String>()
Dans votre activité, observez ce champ et, s’il est modifié, mettez à jour le titre de la barre d’outils.
viewModel?.title?.observe(this, Observer {
my_toolbar.title=it
})
À partir du fragment souhaité, changez le champ de titre dans le modèle de vue.
viewModel?.title?.value="New title"
Jusqu'à ce que le numéro soit corrigé, un simple auditeur fonctionne pour moi:
/**
* 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
}
}
changer le titre du fragment:
(activity as TempToolbarTitleListener).updateTitle("custom title")
En essayant le titre de l'activité, il semble remplacer le titre de fragment. Pour être sûr, vous devez mettre onResume
.
override fun onResume() {
super.onResume()
activity?.toolbar.title = "YOUR_TITLE_HERE"
}
ça marche pour moi !
Note: Doit avoir un widget Barre d'outils en activité
Ajouter une barre d'outils comme celle-ci dans le fichier XML de votre activité
<?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>