Jetpack Compose offre un'implementazione di Material Design, un sistema di progettazione completo per la creazione di interfacce digitali. I componenti di Material Design (pulsanti, schede, interruttori e così via) sono basati su Material Theming, un modo sistematico per personalizzare Material Design in modo da riflettere meglio il brand del tuo prodotto. Un tema Material contiene gli attributi colore, tipografia e forma. Quando personalizzi questi attributi, le modifiche vengono automaticamente riportate nei componenti che utilizzi per creare l'app.
Jetpack Compose implementa questi concetti con il composable MaterialTheme:
MaterialTheme( colors = // ... typography = // ... shapes = // ... ) { // app content }
Configura i parametri che passi a MaterialTheme per applicare il tema alla tua applicazione.
Colore
I colori vengono modellati in Compose con la classe Color, una classe di contenimento dei dati.
val Red = Color(0xffff0000) val Blue = Color(red = 0f, green = 0f, blue = 1f)
Anche se puoi organizzarli come preferisci (come costanti di primo livello, all'interno di un singleton o definiti inline), ti consigliamo vivamente di specificare i colori nel tema e di recuperarli da lì. Questo approccio consente di supportare il tema scuro e i temi nidificati.
Compose fornisce la classe Colors per modellare il sistema di colori Material. Colors fornisce funzioni di creazione per creare set di colori
chiari o scuri:
private val Yellow200 = Color(0xffffeb46) private val Blue200 = Color(0xff91a4fc) // ... private val DarkColors = darkColors( primary = Yellow200, secondary = Blue200, // ... ) private val LightColors = lightColors( primary = Yellow500, primaryVariant = Yellow400, secondary = Blue700, // ... )
Dopo aver definito i Colors, puoi passarli a un MaterialTheme:
MaterialTheme( colors = if (darkTheme) DarkColors else LightColors ) { // app content }
Utilizzare i colori del tema
Puoi recuperare Colors fornito al componente componibile MaterialTheme
utilizzando MaterialTheme.colors.
Text( text = "Hello theming", color = MaterialTheme.colors.primary )
Colore della superficie e dei contenuti
Molti componenti accettano una coppia di colori e colori dei contenuti:
Surface( color = MaterialTheme.colors.surface, contentColor = contentColorFor(color), // ... ) { /* ... */ } TopAppBar( backgroundColor = MaterialTheme.colors.primarySurface, contentColor = contentColorFor(backgroundColor), // ... ) { /* ... */ }
In questo modo, puoi non solo impostare il colore di un componente componibile,ma anche fornire un
colore predefinito per i contenuti e i componenti componibili contenuti al suo interno. Molti
composable utilizzano questo colore dei contenuti per impostazione predefinita. Ad esempio, Text basa il suo
colore su quello dei contenuti del relativo elemento principale e Icon utilizza questo colore per impostare la sua tonalità.
Il metodo contentColorFor() recupera il colore "on" appropriato per
qualsiasi colore del tema. Ad esempio, se imposti un colore di sfondo primary su
Surface, utilizza questa funzione per impostare onPrimary come colore dei contenuti.
Se imposti un colore di sfondo diverso da quello del tema, devi specificare anche un colore
appropriato per i contenuti. Utilizza LocalContentColor per recuperare il colore dei contenuti preferito
per lo sfondo corrente, in una determinata posizione della gerarchia.
Alpha dei contenuti
Spesso vuoi variare l'enfasi sui contenuti per comunicarne l'importanza e fornire una gerarchia visiva. I consigli di leggibilità del testo di Material Design suggeriscono di utilizzare diversi livelli di opacità per comunicare diversi livelli di importanza.
Jetpack Compose implementa questa funzionalità utilizzando LocalContentAlpha. Puoi specificare
un alpha dei contenuti per una gerarchia fornendo un valore per questo
CompositionLocal. I composable nidificati possono utilizzare questo valore per applicare il
trattamento alfa ai propri contenuti. Ad esempio, Text e Icon per impostazione predefinita utilizzano la combinazione di LocalContentColor modificata per utilizzare LocalContentAlpha. Materiale specifica alcuni valori alfa standard
(high, medium, disabled) modellati dall'oggetto
ContentAlpha.
// By default, both Icon & Text use the combination of LocalContentColor & // LocalContentAlpha. De-emphasize content by setting content alpha CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) { Text( // ... ) } CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) { Icon( // ... ) Text( // ... ) }
Per scoprire di più su CompositionLocal, consulta Dati con ambito locale con
CompositionLocal.
ContentAlpha.high. La seconda riga contiene metadati meno importanti e utilizza quindi ContentAlpha.medium.Tema scuro
In Compose, implementi i temi chiaro e scuro fornendo diversi set di
Colors al composable MaterialTheme:
@Composable fun MyTheme( darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit ) { MaterialTheme( colors = if (darkTheme) DarkColors else LightColors, /*...*/ content = content ) }
In questo esempio, MaterialTheme è racchiuso nella propria funzione componibile,
che accetta un parametro che specifica se utilizzare o meno un tema scuro. In
questo caso, la funzione ottiene il valore predefinito per darkTheme eseguendo una query sull'impostazione del tema del dispositivo.
Puoi utilizzare un codice come questo per verificare se le Colors attuali sono chiare o scure:
val isLightTheme = MaterialTheme.colors.isLight Icon( painterResource( id = if (isLightTheme) { R.drawable.ic_sun_24 } else { R.drawable.ic_moon_24 } ), contentDescription = "Theme" )
Overlay di elevazione
In Material, le superfici dei temi scuri con elevazioni più alte ricevono overlay di elevazione, che schiariscono lo sfondo. Più alta è l'elevazione di una superficie (avvicinandola a una sorgente luminosa implicita), più chiara diventa la superficie.
Il composable Surface applica automaticamente queste sovrapposizioni quando si utilizzano
colori scuri, così come qualsiasi altro composable Material che utilizza una superficie:
Surface( elevation = 2.dp, color = MaterialTheme.colors.surface, // color will be adjusted for elevation /*...*/ ) { /*...*/ }
surface come sfondo. Poiché le schede e la navigazione in basso si trovano a livelli di elevazione diversi rispetto allo sfondo, hanno colori leggermente diversi: le schede sono più chiare dello sfondo e la navigazione in basso è più chiara delle schede.Per gli scenari personalizzati che non prevedono un Surface, utilizza
LocalElevationOverlay, un CompositionLocal contenente
ElevationOverlay utilizzato dai componenti Surface:
// Elevation overlays // Implemented in Surface (and any components that use it) val color = MaterialTheme.colors.surface val elevation = 4.dp val overlaidColor = LocalElevationOverlay.current?.apply( color, elevation )
Per disattivare le sovrapposizioni di elevazione, fornisci null nel punto scelto di una
gerarchia componibile:
MyTheme { CompositionLocalProvider(LocalElevationOverlay provides null) { // Content without elevation overlays } }
Accenti di colore limitati
Material consiglia di applicare accenti di colore limitati per i temi scuri, preferendo l'utilizzo del colore surface rispetto al colore primary nella maggior parte dei casi. I composable Material come TopAppBar e BottomNavigation
implementano questo comportamento per impostazione predefinita.
Per gli scenari personalizzati, utilizza la proprietà di estensione primarySurface:
Surface( // Switches between primary in light theme and surface in dark theme color = MaterialTheme.colors.primarySurface, /*...*/ ) { /*...*/ }
Tipografia
Material definisce un sistema di tipi, incoraggiandoti a utilizzare un numero ridotto di stili con nomi semantici.
Compose implementa il sistema di tipi con le classi Typography,
TextStyle e relative ai caratteri. Il costruttore Typography
offre valori predefiniti per ogni stile, quindi puoi omettere quelli che non vuoi personalizzare:
val raleway = FontFamily( Font(R.font.raleway_regular), Font(R.font.raleway_medium, FontWeight.W500), Font(R.font.raleway_semibold, FontWeight.SemiBold) ) val myTypography = Typography( h1 = TextStyle( fontFamily = raleway, fontWeight = FontWeight.W300, fontSize = 96.sp ), body1 = TextStyle( fontFamily = raleway, fontWeight = FontWeight.W600, fontSize = 16.sp ) /*...*/ ) MaterialTheme(typography = myTypography, /*...*/) { /*...*/ }
Se vuoi utilizzare lo stesso tipo di carattere ovunque, specifica il parametro
defaultFontFamily e ometti fontFamily di qualsiasi elemento
TextStyle:
val typography = Typography(defaultFontFamily = raleway) MaterialTheme(typography = typography, /*...*/) { /*...*/ }
Utilizzare gli stili di testo
Agli elementi TextStyle si accede utilizzando MaterialTheme.typography. Recupera
gli elementi TextStyle nel seguente modo:
Text( text = "Subtitle2 styled", style = MaterialTheme.typography.subtitle2 )
Forma
Material definisce un sistema di forme che ti consente di definire le forme per componenti grandi, medi e piccoli.
Compose implementa il sistema di forme con la classe Shapes, che consente
di specificare una CornerBasedShape per ogni categoria di dimensioni:
val shapes = Shapes( small = RoundedCornerShape(percent = 50), medium = RoundedCornerShape(0f), large = CutCornerShape( topStart = 16.dp, topEnd = 0.dp, bottomEnd = 0.dp, bottomStart = 16.dp ) ) MaterialTheme(shapes = shapes, /*...*/) { /*...*/ }
Molti componenti utilizzano queste forme per impostazione predefinita. Ad esempio, Button,
TextField e FloatingActionButton sono impostati per impostazione predefinita su small,
AlertDialog è impostato per impostazione predefinita su medium e ModalDrawer è impostato per impostazione predefinita su
large. Consulta il riferimento allo schema delle forme per la mappatura
completa.
Utilizzare le forme
Agli elementi Shape si accede utilizzando MaterialTheme.shapes. Recupera gli elementi
Shape con un codice simile a questo:
Surface( shape = MaterialTheme.shapes.medium, /*...*/ ) { /*...*/ }
Stili predefiniti
In Compose non esiste un concetto equivalente di stili predefiniti delle View di Android. Puoi fornire funzionalità simili creando overload
funzioni componibili che racchiudono i componenti Material. Ad esempio, per creare uno
stile di pulsante, racchiudi un pulsante nella tua funzione componibile, impostando direttamente
i parametri che vuoi o devi modificare ed esponendo gli altri come parametri al
componente componibile contenitore.
@Composable fun MyButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( backgroundColor = MaterialTheme.colors.secondary ), onClick = onClick, modifier = modifier, content = content ) }
Overlay dei temi
Puoi ottenere l'equivalente delle sovrapposizioni di temi dalle visualizzazioni di Android in Compose nidificando i composable MaterialTheme. Poiché
MaterialTheme imposta i colori, la tipografia e le forme sul valore del tema
corrente, tutti gli altri parametri mantengono i valori predefiniti quando un tema imposta
solo uno di questi parametri.
Inoltre, quando esegui la migrazione delle schermate basate su View a Compose, fai attenzione agli utilizzi
dell'attributo android:theme. Probabilmente ti serve un nuovo MaterialTheme
in quella parte dell'albero della UI di Compose.
In questo esempio, la schermata dei dettagli utilizza un PinkTheme per la maggior parte dello schermo
e poi un BlueTheme per la sezione correlata. Lo screenshot e il
codice riportati di seguito illustrano questo concetto:
@Composable fun DetailsScreen(/* ... */) { PinkTheme { // other content RelatedSection() } } @Composable fun RelatedSection(/* ... */) { BlueTheme { // content } }
Stati dei componenti
I componenti Material con cui è possibile interagire (cliccare, attivare/disattivare e così via) possono trovarsi in stati visivi diversi. Gli stati includono abilitato, disabilitato, premuto e così via.
I composable spesso hanno un parametro enabled. Se lo imposti su false, l'interazione
viene impedita e le proprietà come il colore e l'elevazione vengono modificate per comunicare visivamente
lo stato del componente.
enabled = true (sinistra) e enabled = false (destra).Nella maggior parte dei casi puoi fare affidamento sui valori predefiniti per colore ed elevazione. Se devi configurare i valori utilizzati in stati diversi, sono disponibili classi e funzioni di utilità. Considera il seguente esempio di pulsante:
Button( onClick = { /* ... */ }, enabled = true, // Custom colors for different states colors = ButtonDefaults.buttonColors( backgroundColor = MaterialTheme.colors.secondary, disabledBackgroundColor = MaterialTheme.colors.onBackground .copy(alpha = 0.2f) .compositeOver(MaterialTheme.colors.background) // Also contentColor and disabledContentColor ), // Custom elevation for different states elevation = ButtonDefaults.elevation( defaultElevation = 8.dp, disabledElevation = 2.dp, // Also pressedElevation ) ) { /* ... */ }
enabled = true (a sinistra) e enabled = false (a destra), con valori di colore ed elevazione regolati.Increspature
I componenti Material utilizzano gli effetti ripple per indicare che si sta interagendo con loro. Se
utilizzi MaterialTheme nella gerarchia, Ripple viene utilizzato come
Indication predefinito all'interno di modificatori come clickable e
indication.
Nella maggior parte dei casi puoi fare affidamento al valore predefinito Ripple. Se devi
configurarne l'aspetto, puoi utilizzare RippleTheme per modificare proprietà
come colore e alpha.
Puoi estendere RippleTheme e utilizzare le funzioni di utilità defaultRippleColor e
defaultRippleAlpha. Puoi quindi fornire il tema
ripple personalizzato nella gerarchia utilizzando LocalRippleTheme:
@Composable fun MyApp() { MaterialTheme { CompositionLocalProvider( LocalRippleTheme provides SecondaryRippleTheme ) { // App content } } } @Immutable private object SecondaryRippleTheme : RippleTheme { @Composable override fun defaultColor() = RippleTheme.defaultRippleColor( contentColor = MaterialTheme.colors.secondary, lightTheme = MaterialTheme.colors.isLight ) @Composable override fun rippleAlpha() = RippleTheme.defaultRippleAlpha( contentColor = MaterialTheme.colors.secondary, lightTheme = MaterialTheme.colors.isLight ) }
RippleTheme.Scopri di più
Per saperne di più sui temi Material in Compose, consulta le seguenti risorse aggiuntive.
Codelab
Video
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Sistemi di progettazione personalizzati in Compose
- Migrazione da Material 2 a Material 3 in Compose
- Accessibilità in Scrivi