Prendre en charge le contenu adaptable à la taille de l'écran

Implémentez des gestes de pincement pour zoomer afin de prendre en charge le contenu évolutif dans votre application. Il s'agit de la méthode standard et cohérente avec la plate-forme pour améliorer l'accessibilité, qui permet aux utilisateurs d'ajuster intuitivement la taille du texte et des éléments d'interface utilisateur en fonction de leurs besoins. Votre application peut définir un comportement de mise à l'échelle personnalisé avec un contrôle précis et un comportement contextuel qui offre une expérience que les utilisateurs découvrent souvent plus rapidement qu'une fonctionnalité au niveau du système, comme l'agrandissement de l'écran.

Choisir une stratégie de scaling

Les stratégies décrites dans ce guide entraînent la redistribution et la réorganisation de l'interface utilisateur pour l'adapter à la largeur de l'écran. Cela offre un avantage significatif en termes d'accessibilité, car cela élimine le besoin de panoramique horizontal et le mouvement frustrant en "zig-zag" qui serait autrement nécessaire pour lire de longues lignes de texte.

En savoir plus : les recherches confirment que pour les utilisateurs souffrant d'une déficience visuelle, le contenu redistribué est beaucoup plus lisible et plus facile à parcourir que les interfaces qui nécessitent un panoramique bidimensionnel. Pour en savoir plus, consultez Comparaison entre le contenu panoramique et le contenu redistribuable sur les appareils mobiles.

Mettre à l'échelle tous les éléments ou seulement les éléments de texte

Le tableau suivant illustre l'effet visuel de chaque stratégie de scaling.

Stratégie Scaling de la densité Mise à l'échelle de la police

Comportement

Redimensionne tous les éléments de manière proportionnelle. Le contenu est redistribué pour s'adapter à son conteneur, de sorte que l'utilisateur n'a pas besoin de faire un panoramique horizontal pour voir tout le contenu.

N'affecte que les éléments de texte. La mise en page globale et les composants non textuels conservent la même taille.

What Scales

Tous les éléments visuels : texte, composants (boutons, icônes), images et espacement de la mise en page (marge intérieure, marges)

Texte uniquement

Démonstration

Recommandations

Maintenant que vous avez vu les différences visuelles, le tableau suivant vous aide à peser le pour et le contre, et à choisir la meilleure stratégie pour votre contenu.

Type d'interface utilisateur

Stratégie recommandée

Raisonnement

Mises en page axées sur la lecture

Exemples : articles d'actualité, applications de chat

Densité ou mise à l'échelle de la police

La mise à l'échelle de la densité est préférable pour mettre à l'échelle l'ensemble de la zone de contenu, y compris les images intégrées.

La mise à l'échelle des polices est une alternative simple si seul le texte doit être mis à l'échelle.

Mises en page visuellement structurées

Exemples : magasins d'applications, flux de réseaux sociaux

Mise à l'échelle de la densité

Préserve les relations visuelles entre les images et le texte dans les carrousels ou les grilles. La redistribution évite le panoramique horizontal, qui entrerait en conflit avec les éléments de défilement imbriqués.

Détecter les gestes de mise à l'échelle dans Jetpack Compose

Pour permettre aux utilisateurs de redimensionner le contenu, vous devez d'abord détecter les gestes à plusieurs doigts. Dans Jetpack Compose, vous pouvez utiliser Modifier.transformable.

Le modificateur transformable est une API de haut niveau qui fournit le delta zoomChange depuis le dernier événement de geste. Cela simplifie la logique de mise à jour de l'état en accumulation directe (par exemple, scale *= zoomChange), ce qui est idéal pour les stratégies de scaling adaptatif abordées dans ce guide.

Exemples de mise en œuvre

Les exemples suivants montrent comment implémenter les stratégies de mise à l'échelle de la densité et de la police.

Scaling de la densité

Cette approche permet de mettre à l'échelle la valeur density de base d'une zone de l'UI. Par conséquent, toutes les mesures basées sur la mise en page (y compris la marge intérieure, l'espacement et la taille des composants) sont mises à l'échelle, comme si la taille ou la résolution de l'écran avaient changé. Comme la taille du texte dépend également de la densité, elle est également mise à l'échelle proportionnellement. Cette stratégie est efficace lorsque vous souhaitez agrandir uniformément tous les éléments d'une zone spécifique, en conservant le rythme visuel global et les proportions de votre UI.

private class DensityScalingState(
    // Note: For accessibility, typical min/max values are ~0.75x and ~3.5x.
    private val minScale: Float = 0.75f,
    private val maxScale: Float = 3.5f,
    private val currentDensity: Density
) {
    val transformableState = TransformableState { zoomChange, _, _ ->
        scaleFactor.floatValue =
            (scaleFactor.floatValue * zoomChange).coerceIn(minScale, maxScale)
    }
    val scaleFactor = mutableFloatStateOf(1f)
    fun scaledDensity(): Density {
        return Density(
            currentDensity.density * scaleFactor.floatValue,
            currentDensity.fontScale
        )
    }
}

@Composable
fun DensityScalingSample() {
    val currentDensity = LocalDensity.current
    val scaleState =
        remember(currentDensity) { DensityScalingState(currentDensity = currentDensity) }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .transformable(state = scaleState.transformableState),
        contentAlignment = Alignment.TopCenter
    ) {
        CompositionLocalProvider(
            LocalDensity provides scaleState.scaledDensity()
        ) {
            DemoCard()
        }
    }
}

Mise à l'échelle de la police

Cette stratégie est plus ciblée, car elle ne modifie que le facteur fontScale. Par conséquent, seuls les éléments de texte s'agrandissent ou rétrécissent, tandis que tous les autres composants de mise en page (comme les conteneurs, la marge intérieure et les icônes) conservent une taille fixe. Cette stratégie est bien adaptée pour améliorer la lisibilité du texte dans les applications nécessitant une lecture intensive.

class FontScaleState(
    // Note: For accessibility, typical min/max values are ~0.75x and ~3.5x.
    private val minScale: Float = 0.75f,
    private val maxScale: Float = 3.5f,
    private val currentDensity: Density
) {
    val transformableState = TransformableState { zoomChange, _, _ ->
        scaleFactor.floatValue =
            (scaleFactor.floatValue * zoomChange).coerceIn(minScale, maxScale)
    }
    val scaleFactor = mutableFloatStateOf(1f)
    fun scaledFont(): Density {
        return Density(
            currentDensity.density,
            currentDensity.fontScale * scaleFactor.floatValue
        )
    }
}

@Composable
fun FontScalingSample() {
    val currentDensity = LocalDensity.current
    val scaleState = remember { FontScaleState(currentDensity = currentDensity) }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .transformable(state = scaleState.transformableState),
        contentAlignment = Alignment.TopCenter
    ) {
        CompositionLocalProvider(
            LocalDensity provides scaleState.scaledFont()
        ) {
            DemoCard()
        }
    }
}

UI de démonstration partagée

Il s'agit du composable DemoCard partagé utilisé par les deux exemples précédents pour mettre en évidence les différents comportements de mise à l'échelle.

@Composable
private fun DemoCard() {
    Card(
        modifier = Modifier
            .width(360.dp)
            .padding(16.dp),
        shape = RoundedCornerShape(12.dp)
    ) {
        Column(
            modifier = Modifier.padding(16.dp),
            verticalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            Text("Demo Card", style = MaterialTheme.typography.headlineMedium)
            var isChecked by remember { mutableStateOf(true) }
            Row(verticalAlignment = Alignment.CenterVertically) {
                Text("Demo Switch", Modifier.weight(1f), style = MaterialTheme.typography.bodyLarge)
                Switch(checked = isChecked, onCheckedChange = { isChecked = it })
            }
            Row(verticalAlignment = Alignment.CenterVertically) {
                Icon(Icons.Filled.Person, "Icon", Modifier.size(32.dp))
                Spacer(Modifier.width(8.dp))
                Text("Demo Icon", style = MaterialTheme.typography.bodyLarge)
            }
            Row(
                Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceBetween
            ) {
                Box(
                    Modifier
                        .width(100.dp)
                        .weight(1f)
                        .height(80.dp)
                        .background(Color.Blue)
                )
                Box(
                    Modifier
                        .width(100.dp)
                        .weight(1f)
                        .height(80.dp)
                        .background(Color.Red)
                )
            }
            Text(
                "Demo Text: Lorem ipsum dolor sit amet, consectetur adipiscing elit," +
                    " sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
                style = MaterialTheme.typography.bodyMedium,
                textAlign = TextAlign.Justify
            )
        }
    }
}

Conseils et points à noter

Pour créer une expérience plus soignée et accessible, tenez compte des recommandations suivantes :

  • Envisagez de proposer des commandes de mise à l'échelle sans gestes : certains utilisateurs peuvent avoir des difficultés avec les gestes. Pour aider ces utilisateurs, envisagez de proposer une autre méthode pour ajuster ou réinitialiser l'échelle, qui ne repose pas sur des gestes.
  • Concevez pour toutes les échelles : testez votre UI avec la mise à l'échelle dans l'application et les paramètres de police ou d'affichage à l'échelle du système. Vérifiez que les mises en page de votre application s'adaptent correctement sans casser, chevaucher ou masquer le contenu. Découvrez comment créer des mises en page adaptatives.