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, opzioni e così via) sono basati sui temi di Material, un modo sistematico per personalizzare Material Design in modo da riflettere meglio il brand del tuo prodotto. Un tema di Material contiene attributi di colore, tipografia e forma. Quando personalizzi questi attributi, le modifiche vengono applicate automaticamente ai componenti che utilizzi per creare l'app.
Jetpack Compose implementa questi concetti con il componibile MaterialTheme:
MaterialTheme( colors = // ... typography = // ... shapes = // ... ) { // app content }
Configura i parametri che passi a MaterialTheme per applicare un tema alla tua applicazione.
Colore
I colori sono modellati in Compose con la classe Color, una classe di conservazione dei dati.
val Red = Color(0xffff0000) val Blue = Color(red = 0f, green = 0f, blue = 1f)
Sebbene tu possa organizzarli come preferisci (come costanti di primo livello, all'interno di un singleton o definiti in linea), 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 di 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 }
Usa i colori del tema
Puoi recuperare il Colors fornito all'elemento composable 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, non solo puoi impostare il colore di un composable, ma anche fornire un colore predefinito per i contenuti, ovvero i composable contenuti al suo interno. Molti composabili utilizzano questo colore dei contenuti per impostazione predefinita. Ad esempio, Text basa il suo colore sul colore dei contenuti del componente principale e Icon utilizza quel colore per impostare la sua tinta.
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 non del tema, devi anche specificare un colore dei contenuti appropriato. Utilizza LocalContentColor per recuperare il colore dei contenuti preferito per lo sfondo corrente, in una determinata posizione della gerarchia.
Alpha dei contenuti
Spesso è necessario variare l'enfasi dei contenuti per comunicare l'importanza e fornire una gerarchia visiva. I consigli sulla 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 valore alfa dei contenuti per una gerarchia fornendo un valore per questo CompositionLocal. I componibili 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. Material specifica alcuni valori alfa standard (high, medium, disabled) che vengono 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, quindi utilizza 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 è aggregato 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 i Colors correnti sono chiari o scuri:
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 altitudine
In Material, le superfici nei temi scuri con elevazioni più elevate ricevono overlay di elevazione, che ne schiariscono lo sfondo. Più alta è l'elevazione di una superficie (che la avvicina a una fonte di luce implicita), più chiara diventa la superficie.
Il componibile Surface applica automaticamente questi overlay quando si utilizzano colori scuri, così come qualsiasi altro componibile 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 barra di 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 barra di navigazione in basso è più chiara delle schede.Per gli scenari personalizzati che non coinvolgono 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 gli overlay 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'uso del colore surface rispetto al colore primary nella maggior parte dei casi. I componibili 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, in modo da poter 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 carattere tipografico ovunque, specifica il parametro defaultFontFamily e ometti fontFamily di tutti gli elementi TextStyle:
val typography = Typography(defaultFontFamily = raleway) MaterialTheme(typography = typography, /*...*/) { /*...*/ }
Utilizza gli stili di testo
Gli elementi TextStyle sono accessibili tramite MaterialTheme.typography. Recupera gli elementi TextStyle come segue:
Text( text = "Subtitle2 styled", style = MaterialTheme.typography.subtitle2 )
Forma
Material definisce un sistema di forme che ti consente di definire le forme per i componenti grandi, medi e piccoli.
Compose implementa il sistema di forme con la classe Shapes, che ti consente di specificare un 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 su medium e ModalDrawer su large. Per la mappatura completa, consulta il riferimento allo schema delle forme.
Utilizza le forme
Gli elementi Shape sono accessibili tramite MaterialTheme.shapes. Recupera gli elementi Shape con un codice simile al seguente:
Surface( shape = MaterialTheme.shapes.medium, /*...*/ ) { /*...*/ }
Stili predefiniti
In Compose non esiste un concetto equivalente agli stili predefiniti delle visualizzazioni Android. Puoi fornire una funzionalità simile creando le tue funzioni componibili overload che aggregano i componenti Material. Ad esempio, per creare uno stile di pulsante, inserisci un pulsante nella tua funzione componibile, impostando direttamente i parametri che vuoi o devi modificare ed esponendo gli altri come parametri al 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 degli overlay dei temi dalle visualizzazioni Android in Compose nidificando i componibili MaterialTheme. Poiché
MaterialTheme imposta i colori, la tipografia e le forme sui valori del tema
corrente, tutti gli altri parametri mantengono i valori predefiniti quando un tema imposta
solo uno di questi parametri.
Inoltre, durante la migrazione delle schermate basate su View a Compose, fai attenzione agli utilizzi dell'attributo android:theme. È probabile che tu abbia bisogno di 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 della schermata e un BlueTheme per la sezione correlata. Lo screenshot e il codice seguenti 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 (clic, attivazione/disattivazione e così via) possono trovarsi in stati visivi diversi. Gli stati includono attivato, disattivato, premuto e così via.
I componibili spesso hanno un parametro enabled. Se lo imposti su false, l'interazione viene impedita e vengono modificate proprietà come il colore e l'elevazione 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 elementi come colore e rilievo. Se devi configurare i valori utilizzati in stati diversi, sono disponibili classi e funzioni di convenienza. 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 e altezza modificati.Increspature
I componenti Material utilizzano gli effetti ripple per indicare che sono in corso interazioni. Se utilizzi MaterialTheme nella tua gerarchia, viene utilizzato un Ripple come Indication predefinito all'interno di modificatori come clickable e indication.
Nella maggior parte dei casi puoi fare affidamento sul valore predefinito Ripple. Se devi configurare il loro aspetto, puoi utilizzare RippleTheme per modificare proprietà come il colore e l'alpha.
Puoi estendere RippleTheme e utilizzare le funzioni di utilità defaultRippleColor e defaultRippleAlpha. Puoi quindi fornire il tuo tema di 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 ) }
RippleConfiguration.Scopri di più
Per scoprire di più sui temi di 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
- Esegui la migrazione da Material 2 a Material 3 in Compose
- Accessibilità in Compose