web-dev-qa-db-fra.com

Titre de barre d'action dynamique à partir d'un fragment utilisant AndroidX Navigation

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?

23
Jonas

À 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.

38
CommonsWare

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

6
Bradleycorn

Si vous considérez que votre activité hôte est MainActivity, ajoutez simplement le code suivant à votre MainActivityonCreate 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
}
5
Kaustubh Trivedi

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()
}
3
Hussnain Haidar

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");
3
Naveen Rao

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"
3
Alex

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")
1
Francis

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>
0
Dilroop Singh