Navigation pliable

Le composant de navigation pliable est une bibliothèque basée sur le composant de navigation Android. Il permet aux développeurs d’implémenter la navigation dans des fragments pour différents modes d’écran ou d’adapter une application existante à un modèle de navigation pliable.

Le composant de navigation pliable se compose de trois parties principales :

  • Graphe de navigation : ressource XML contenant toutes les informations relatives à la navigation dans un emplacement centralisé. Ce graphe est identique à celui du composant de navigation fourni par Google.
  • FoldableNavHost : conteneur vide qui affiche les destinations à partir de votre graphe de navigation. L’implémentation de la navigation pliable est FoldableNavHostFragment.
  • FoldableNavController : objet qui gère la navigation dans une application dans un FoldableNavHost.

Vue d’ensemble

Les applications sur des appareils double écran et pliables peuvent être affichées sur un seul écran ou étendues avec une fonctionnalité de pliage. Quand l’application est démarrée pour la première fois :

  • Dans un seul écran, un seul fragment (A) est visible.
  • Si l’application est étendue avec une fonctionnalité de pliage, le premier fragment (A) se trouve sur le premier côté du pli et l’autre côté du pli est vide.

À partir de l’état initial, si vous accédez à un autre fragment (B), le nouveau fragment s’ouvre sur l’écran de fin.

Si l’utilisateur accède à un troisième fragment (C), celui-ci apparaît sur l’écran de fin. Le fragment précédent (B) est alors déplacé vers l’écran de départ.

  • Quand une application passe du mode étendu à un seul écran, tous les fragments de l’écran de fin sont déplacés vers l’écran de départ et (C) apparaît dans la partie supérieure.
  • Quand l’application passe d’un seul écran au mode étendu avec un pli ou une charnière et que la pile de navigation comporte plus de deux fragments, le dernier fragment est déplacé vers l’écran de fin.

Six different dual-screen examples demonstrating how fragments A, B, and C would appear after different navigation steps

Modifier la destination de la zone d’affichage pour des actions

Vous pouvez spécifier où un nouveau fragment sera affiché avec l’attribut launchScreen dans le graphe de navigation. Les valeurs possibles pour launchScreen sont :

  • start : le fragment est ouvert sur le premier écran
  • end : le fragment est ouvert sur le deuxième écran
  • both : le fragment couvre toute la zone d’affichage

Cet exemple de fichier XML de navigation montre comment utiliser cet attribut :

<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/home"
    app:startDestination="@+id/titleScreen">

    <fragment
        android:id="@+id/titleScreen"
        android:name="com.microsoft.device.dualscreen.navigation.sample.homescreen.TitleFragment"
        android:label="@string/title_home"
        tools:layout="@layout/fragment_title">
        <action
            android:id="@+id/action_title_to_about"
            app:launchScreen="end"
            app:destination="@id/aboutScreen"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_right"
            app:popExitAnim="@anim/slide_out_left" />
    </fragment>
</navigation>

Important

Pour modifier cet attribut, vous devez modifier directement le fichier XML. Vous ne pouvez pas le modifier avec Android Studio Editor.

Exemple

Vous pouvez télécharger cet exemple d’application de navigation pour voir tous ces comportements.

Comment importer la bibliothèque dans votre projet

  1. Ajoutez la dépendance au fichier build.gradle au niveau du module :

    dependencies {
       def nav_version = "1.0.0-alpha3"
       implementation "com.microsoft.device.dualscreen:navigation-fragment-ktx:$nav_version"
       implementation "com.microsoft.device.dualscreen:navigation-ui-ktx:$nav_version"
    }
    

  1. Si votre projet est créé avec Java, vous devez ajouter une dépendance kotlin-stdlib à votre fichier build.gradle au niveau du module. (Cela est dû au fait qu’une partie de la bibliothèque a été créée avec Kotlin.)

    dependencies {
       implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    }
    

Ces composants étant basés sur le composant Navigation fourni par Google, la bibliothèque Foldable-Navigation contient une dépendance à ce composant.

Créer un graphe de navigation

Un graphe de navigation est un fichier de ressources XML contenant tous les chemins de navigation de votre application, avec des destinations et des actions. Vous pouvez créer le graphe de navigation avec Android Studio Navigation Editor ou manuellement avec un éditeur XML. Pour plus d’informations, consultez Créer un graphe de navigation.

Ajouter un NavHost à une activité

Le composant de navigation pliable est conçu pour les applications avec une activité principale et plusieurs fragments de destination. L’activité principale est associée à un graphe de navigation et contient un FoldableNavHostFragment en charge de la permutation des fragments de destination. Si votre application a plusieurs activités, chaque activité a son propre graphe de navigation.

Voici un exemple du fichier de disposition XML d’une activité principale qui montre comment définir l’attribut app:navGraph :

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/surface_duo_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.FoldableNavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>

FoldableNavHost peut également être défini par programmation :

val navHostFragment = FoldableNavHostFragment.create(navGraphId)
fragmentManager.beginTransaction()
    .add(containerId, navHostFragment, fragmentTag)
    .commitNow()

Pour plus d’informations sur l’ajout de FoldableNavHost, consultez Ajouter un NavHost à une activité.

Cet extrait de code peut être utilisé pour parcourir des fragments en fonction de règles de navigation pliable :

class SomeFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        view.findViewById<Button>(R.id.btn_next).setOnClickListener {
            findFoldableNavController().navigate(R.id.action_next)
        }
    }
}

Mettre à jour les composants d’interface utilisateur avec FoldableNavigationUI

FoldableNavigationUI est un composant similaire à NavigationUI dans le composant Navigation de Jetpack. Il contient des méthodes statiques qui permettent de gérer la navigation avec la barre d’application supérieure, le tiroir de navigation et la navigation inférieure. Vous trouverez plus d’informations sur

FoldableNavigationUI contient les méthodes suivantes, similaires à celles fournies par NavigationUI :

// same method name, with foldable parameter
boolean onNavDestinationSelected(MenuItem item, FoldableNavController navController)
boolean navigateUp(FoldableNavController navController, Openable openableLayout)
boolean navigateUp(FoldableNavController navController, FoldableAppBarConfiguration configuration)
// method name changed to reflect foldable navigation
void setupActionBarWithFoldableNavController(AppCompatActivity activity, FoldableNavController navController)
void setupActionBarWithFoldableNavController(AppCompatActivity activity, FoldableNavController navController, Openable openableLayout)
void setupActionBarWithFoldableNavController(AppCompatActivity activity, FoldableNavController navController, FoldableAppBarConfiguration configuration)
void setupWithFoldableNavController(Toolbar toolbar, FoldableNavController navController)
void setupWithFoldableNavController(Toolbar toolbar, FoldableNavController navController, Openable openableLayout)
void setupWithFoldableNavController(Toolbar toolbar, FoldableNavController navController, FoldableAppBarConfiguration configuration)
void setupWithFoldableNavController(CollapsingToolbarLayout collapsingToolbarLayout, Toolbar toolbar, FoldableNavController navController)
void setupWithFoldableNavController(CollapsingToolbarLayout collapsingToolbarLayout, Toolbar toolbar, FoldableNavController navController, Openable openableLayout)
void setupWithFoldableNavController(CollapsingToolbarLayout collapsingToolbarLayout, Toolbar toolbar, FoldableNavController navController, FoldableAppBarConfiguration configuration)
void setupWithFoldableNavController(NavigationView navigationView, FoldableNavController navController)
void setupWithFoldableNavController(BottomNavigationView bottomNavigationView, FoldableNavController navController)

Migrer des applications existantes vers une navigation pliable

Pour les applications existantes qui utilisent le composant Navigation fourni par Google, vous pouvez ajouter une fonctionnalité pliable en effectuant les étapes suivantes :

  1. Utilisez FoldableNavHostFragment plutôt que NavHostFragment dans la vue de conteneur de fragments en remplaçant

    <androidx.fragment.app.FragmentContainerView
         android:id="@+id/nav_host_fragment"
         android:name="androidx.navigation.NavHostFragment"
    

    to

    <androidx.fragment.app.FragmentContainerView
         android:id="@+id/nav_host_fragment"
         android:name="androidx.navigation.FoldableNavHostFragment"
    
  2. Utilisez findFoldableNavController pour obtenir l’instance de FoldableNavController et servez-vous-en pour naviguer dans le graphe de navigation en remplaçant

    findNavController().navigate(R.id.action_next)
    

    to

    findFoldableNavController().navigate(R.id.action_next)
    
  3. Utilisez FoldableNavigationUI plutôt que NavigationUI en remplaçant

    val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
    val appBarConfiguration = AppBarConfiguration(navController.graph)
    setupActionBarWithNavController(navController, appBarConfiguration)
    

    to

    val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as FoldableNavHostFragment
    val navController = navHostFragment.navController
    val appBarConfiguration = FoldableAppBarConfiguration(navController.graph)
    setupActionBarWithFoldableNavController(navController, appBarConfiguration)