Assurer la compatibilité avec différentes tailles d'écran

La compatibilité avec différentes tailles d'écran permet d'accéder à votre appli sur une large gamme d'appareils et pour un plus grand nombre d'utilisateurs.

Pour accepter un maximum de tailles d'écran, concevez vos mises en page d'application de sorte qu'elles soient responsives et adaptatives. Les mises en page responsives et adaptatives offrent une expérience utilisateur optimisée, quelle que soit la taille de l'écran. Elles permettent ainsi à votre application de s'adapter aux téléphones, aux tablettes, aux appareils pliables et aux appareils ChromeOS, ainsi qu'aux orientations portrait et paysage, et aux configurations redimensionnables comme le mode multifenêtre.

Classes de taille de fenêtre

Les classes de taille de fenêtre sont un ensemble de points d'arrêt de fenêtre d'affichage définis qui permettent de concevoir, de développer et de tester des mises en page responsives et adaptatives. Les points d'arrêt équilibrent la simplicité de la mise en page et la flexibilité pour optimiser votre application dans des cas spécifiques.

Les classes de taille de fenêtre distinguent la zone d'affichage disponible sur votre application en trois catégories : Compacte, Moyenne ou Étendue. La largeur et la hauteur disponibles sont évaluées séparément. Votre application peut donc être associée à deux classes de taille de fenêtre : une pour la largeur et une pour la hauteur. La largeur disponible est généralement plus importante que la hauteur disponible en raison de l'omniprésence du défilement vertical. La classe de largeur de fenêtre est donc probablement plus adaptée à l'interface utilisateur de votre application.

Figure 1 : Représentations des classes de largeur de fenêtre.
Figure 2 : Représentations des classes de hauteur de fenêtre.

Comme le montrant les figures, les points d'arrêt vous permettent de continuer à réfléchir aux mises en page selon les appareils et les configurations. Chaque point d'arrêt de classe de taille représente un cas majoritaire pour des scénarios courants d'appareil. Il peut être un cadre de référence utile pour réfléchir à la conception de vos mises en page basées sur des points d'arrêt.

Classe de taille Point d'arrêt Représentation de l'appareil
Largeur compacte largeur < 600 dp 99,96 % des téléphones en mode portrait
Largeur moyenne 600 dp ≤ largeur < 840 dp 93,73 % des tablettes en mode portrait

plus grands écrans internes dépliés en mode portrait

Largeur étendue largeur ≥ 840 dp 97,22 % des tablettes en mode paysage

plus grands écrans internes dépliés en mode paysage

Hauteur compacte hauteur < 480 dp 99,78 % des téléphones en mode paysage
Hauteur moyenne 480 dp ≤ hauteur < 900 dp 96,56 % des tablettes en mode paysage

97,59 % des téléphones en mode portrait

Hauteur étendue hauteur ≥ 900 dp 94,25 % des tablettes en mode portrait

Bien qu'il puisse être utile de visualiser les classes de taille en tant qu'appareils physiques, les classes de taille de fenêtre ne sont pas explicitement déterminées par la taille de l'écran de l'appareil. Les classes de taille de fenêtre ne sont pas conçues dans une logique de type isTablet. Les classes de taille de fenêtre sont déterminées par la taille de la fenêtre disponible pour votre application, quel que soit le type d'appareil sur lequel elle s'exécute, ce qui a deux conséquences importantes :

  • Les appareils physiques ne garantissent pas l'utilisation d'une classe de taille de fenêtre spécifique. L'espace disponible sur votre application peut différer de la taille d'écran de l'appareil pour de nombreuses raisons. Sur les appareils mobiles, le mode Écran partagé peut diviser l'écran entre deux applications. Sous ChromeOS, les applications Android peuvent être présentées dans des fenêtres de format libre qui sont arbitrairement redimensionnables. Les appareils pliables sont équipés de deux écrans de différentes tailles auxquels il est possible d'accéder individuellement en pliant ou en dépliant l'appareil.

  • La classe de taille de fenêtre peut changer tout au long de la durée de vie de votre application. Lorsqu'elle est en cours d'exécution, les changements d'orientation de l'appareil, le mode multitâche et le pliage/dépliage peuvent modifier la quantité d'espace disponible sur l'écran. La classe de taille de fenêtre est donc dynamique, et l'interface utilisateur de votre application doit s'adapter en conséquence.

Les classes de taille de fenêtre sont mappées aux points d'arrêt de mise en page dans la grille de mise en page responsive de Material Design. Utilisez les classes de taille de fenêtre pour prendre des décisions concernant la mise en page des applications de haut niveau, par exemple pour décider d'utiliser une mise en page standard spécifique afin de disposer de plus d'espace à l'écran.

Vous pouvez calculer la WindowSizeClass actuelle à l'aide de la fonction WindowSizeClass#compute() fournie par la bibliothèque Jetpack WindowManager. L'exemple suivant montre comment calculer la classe de taille de fenêtre et recevoir des mises à jour chaque fois que la classe de taille de fenêtre change :

Kotlin

class MainActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ...

        // Replace with a known container that you can safely add a
        // view to where the view won't affect the layout and the view
        // won't be replaced.
        val container: ViewGroup = binding.container

        // Add a utility view to the container to hook into
        // View.onConfigurationChanged(). This is required for all
        // activities, even those that don't handle configuration
        // changes. You can't use Activity.onConfigurationChanged(),
        // since there are situations where that won't be called when
        // the configuration changes. View.onConfigurationChanged() is
        // called in those scenarios.
        container.addView(object : View(this) {
            override fun onConfigurationChanged(newConfig: Configuration?) {
                super.onConfigurationChanged(newConfig)
                computeWindowSizeClasses()
            }
        })

        computeWindowSizeClasses()
    }

    private fun computeWindowSizeClasses() {
        val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this)
        val width = metrics.bounds.width()
        val height = metrics.bounds.height()
        val density = resources.displayMetrics.density
        val windowSizeClass = WindowSizeClass.compute(width/density, height/density)
        // COMPACT, MEDIUM, or EXPANDED
        val widthWindowSizeClass = windowSizeClass.windowWidthSizeClass
        // COMPACT, MEDIUM, or EXPANDED
        val heightWindowSizeClass = windowSizeClass.windowHeightSizeClass

        // Use widthWindowSizeClass and heightWindowSizeClass.
    }
}

Java

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // ...

        // Replace with a known container that you can safely add a
        // view to where the view won't affect the layout and the view
        // won't be replaced.
        ViewGroup container = binding.container;

        // Add a utility view to the container to hook into
        // View.onConfigurationChanged(). This is required for all
        // activities, even those that don't handle configuration
        // changes. You can't use Activity.onConfigurationChanged(),
        // since there are situations where that won't be called when
        // the configuration changes. View.onConfigurationChanged() is
        // called in those scenarios.
        container.addView(new View(this) {
            @Override
            protected void onConfigurationChanged(Configuration newConfig) {
                super.onConfigurationChanged(newConfig);
                computeWindowSizeClasses();
            }
        });

        computeWindowSizeClasses();
    }

    private void computeWindowSizeClasses() {
        WindowMetrics metrics = WindowMetricsCalculator.getOrCreate()
                .computeCurrentWindowMetrics(this);

        int width = metrics.getBounds().width
        int height = metrics.getBounds().height()
        float density = getResources().getDisplayMetrics().density;
        WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density)
        // COMPACT, MEDIUM, or EXPANDED
        WindowWidthSizeClass widthWindowSizeClass = windowSizeClass.getWindowWidthSizeClass()
        // COMPACT, MEDIUM, or EXPANDED
        WindowHeightSizeClass heightWindowSizeClass = windowSizeClass.getWindowHeightSizeClass()

        // Use widthWindowSizeClass and heightWindowSizeClass.
    }
}

Une fois que vous avez observé les classes de taille de fenêtre dans votre application, vous pouvez commencer à modifier la mise en page en fonction de la classe de taille de fenêtre actuelle.

Mises en page et classes de taille de fenêtre

Lorsque vous modifiez la mise en page, testez le comportement de mise en page avec toutes les tailles de fenêtre, en particulier avec les points d'arrêt basés sur la largeur compacte, moyenne et étendue.

Si vous disposez déjà d'une mise en page pour les écrans compacts, commencez par l'optimiser pour la classe de largeur étendue, afin de disposer de plus d'espace pour modifier le contenu et l'interface utilisateur. Ensuite, choisissez la mise en page qui convient pour la classe de largeur moyenne. Envisagez d'ajouter une mise en page spécialisée.

Étapes suivantes

Pour en savoir plus sur l'utilisation des classes de taille de fenêtre pour créer des mises en page responsives/adaptatives, consultez les ressources suivantes :

Pour en savoir plus sur ce qui fait la qualité d'une application sur tous les appareils et toutes les tailles d'écran, consultez les ressources suivantes :