Supportare contenuti scalabili dall'utente

Implementa i gesti di pizzicamento per zoomare per supportare contenuti scalabili nella tua app. Questo è il metodo standard e coerente con la piattaforma per migliorare l'accessibilità, consentendo agli utenti di regolare in modo intuitivo le dimensioni del testo e degli elementi dell'interfaccia utente in base alle loro esigenze. La tua app può definire un comportamento di scalabilità personalizzato con un controllo granulare e un comportamento contestuale che offre un'esperienza che gli utenti spesso scoprono più velocemente di una funzionalità a livello di sistema come l'ingrandimento dello schermo.

Scegliere una strategia di scalabilità

Le strategie trattate in questa guida fanno sì che la UI venga ridisposta e riorganizzata per adattarsi alla larghezza dello schermo. Ciò offre un vantaggio significativo in termini di accessibilità eliminando la necessità di panoramica orizzontale e il frustrante movimento "a zig-zag" che altrimenti sarebbe necessario per leggere lunghe righe di testo.

Approfondimento: la ricerca conferma che per gli utenti con problemi di vista, il reflow dei contenuti è molto più leggibile e facile da navigare rispetto alle interfacce che richiedono lo spostamento bidimensionale. Per maggiori dettagli, vedi Confronto tra panoramica e scansione e contenuti adattabili sui dispositivi mobili.

Scala tutti gli elementi o solo gli elementi di testo

La tabella seguente mostra l'effetto visivo di ciascuna strategia di scalabilità.

Strategia Scalabilità della densità Ridimensionamento carattere

Comportamento

Scala tutto in modo proporzionale. I contenuti vengono ridisposti per adattarsi al contenitore, in modo che l'utente non debba spostarsi orizzontalmente per visualizzarli tutti.

Interessa solo gli elementi di testo. Il layout generale e i componenti non testuali rimangono delle stesse dimensioni.

Che cosa sono le scale?

Tutti gli elementi visivi: testo, componenti (pulsanti, icone), immagini e spaziatura del layout (spaziatura interna, margini)

Solo testo

Dimostrazione

Consigli

Ora che hai visto le differenze visive, la seguente tabella ti aiuta a valutare i compromessi e a scegliere la strategia migliore per i tuoi contenuti.

Tipo di UI

Strategia consigliata

Motivazione

Layout con molti contenuti da leggere

Esempi: articoli di notizie, app di messaggistica

Densità o ridimensionamento dei caratteri

Il ridimensionamento della densità è preferibile per ridimensionare l'intera area dei contenuti, incluse le immagini incorporate.

Il ridimensionamento del carattere è un'alternativa semplice se è necessario ridimensionare solo il testo.

Layout strutturati visivamente

Esempi: store, feed dei social media

Ridimensionamento della densità

Mantiene le relazioni visive tra immagini e testo nei caroselli o nelle griglie. Il reflow evita la panoramica orizzontale, che sarebbe in conflitto con gli elementi di scorrimento nidificati.

Rilevare i gesti di ridimensionamento in Jetpack Compose

Per supportare i contenuti scalabili dall'utente, devi prima rilevare i gesti multitocco. In Jetpack Compose, puoi farlo utilizzando Modifier.transformable.

Il modificatore transformable è un'API di alto livello che fornisce il delta zoomChange dall'ultimo evento di movimento. In questo modo, la logica di aggiornamento dello stato viene semplificata in accumulo diretto (ad esempio, scale *= zoomChange), il che la rende ideale per le strategie di scalabilità adattiva trattate in questa guida.

Esempi di implementazioni

I seguenti esempi mostrano come implementare le strategie di scalabilità della densità e di scalabilità dei caratteri.

Scalabilità della densità

Questo approccio scala la base density di un'area della UI. Di conseguenza, tutte le misurazioni basate sul layout, incluse le dimensioni di riempimento, spaziatura e componenti, vengono ridimensionate, come se le dimensioni o la risoluzione dello schermo fossero cambiate. Poiché le dimensioni del testo dipendono anche dalla densità, vengono scalate proporzionalmente. Questa strategia è efficace quando vuoi ingrandire in modo uniforme tutti gli elementi all'interno di un'area specifica, mantenendo il ritmo visivo complessivo e le proporzioni della tua 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
        )
    }
}

Ridimensionamento carattere

Questa strategia è più mirata e modifica solo il fattore fontScale. Il risultato è che solo gli elementi di testo aumentano o diminuiscono, mentre tutti gli altri componenti del layout, come contenitori, spaziatura interna e icone, rimangono di dimensioni fisse. Questa strategia è adatta per migliorare la leggibilità del testo nelle app che richiedono molta lettura.

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
        )
    }
}

UI demo condivisa

Questo è il composable DemoCard condiviso utilizzato da entrambi gli esempi precedenti per evidenziare i diversi comportamenti di scalabilità.

@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
            )
        }
    }
}

Suggerimenti e considerazioni

Per creare un'esperienza più raffinata e accessibile, tieni presenti i seguenti suggerimenti:

  • Valuta la possibilità di offrire controlli di scala non basati su gesti: alcuni utenti potrebbero avere difficoltà con i gesti. Per supportare questi utenti, valuta la possibilità di fornire un modo alternativo per regolare o reimpostare la bilancia che non si basa sui gesti.
  • Crea per tutte le scale: testa la tua UI con il ridimensionamento in-app e con le impostazioni di sistema per il carattere o la visualizzazione. Verifica che i layout della tua app si adattino correttamente senza interrompere, sovrapporre o nascondere i contenuti. Scopri di più su come creare layout adattivi.