Jetpack Compose bietet eine Implementierung von Material Design, einem umfassenden Designsystem zum Erstellen digitaler Schnittstellen. Die Material Design-Komponenten (Schaltflächen, Karten, Schalter usw.) basieren auf Material Theming, einer systematischen Möglichkeit, Material Design so anzupassen, dass es die Marke Ihres Produkts besser widerspiegelt. Ein Materialdesign enthält die Attribute Farbe, Typografie und Form. Wenn Sie diese Attribute anpassen, werden Ihre Änderungen automatisch in den Komponenten widergespiegelt, die Sie zum Erstellen Ihrer Anwendung verwenden.
Jetpack Compose implementiert diese Konzepte mit der zusammensetzbaren Funktion MaterialTheme
:
MaterialTheme( colors = // ... typography = // ... shapes = // ... ) { // app content }
Konfigurieren Sie die Parameter, die Sie an MaterialTheme
übergeben, um das Design Ihrer Anwendung zu bestimmen.
Abbildung 1: Der erste Screenshot zeigt eine App, in der MaterialTheme
nicht konfiguriert wird und daher einen Standardstil verwendet. Der zweite Screenshot zeigt eine App, die Parameter an MaterialTheme
übergibt, um den Stil anzupassen.
Farbe
Farben werden in Compose mit der Klasse Color
modelliert, einer einfachen Datenspeicherklasse.
val Red = Color(0xffff0000) val Blue = Color(red = 0f, green = 0f, blue = 1f)
Sie können diese beliebig organisieren (als Konstanten auf oberster Ebene, in einem Singleton-Element oder als Inline-Definition). Wir empfehlen jedoch dringend, Farben in Ihrem Design anzugeben und die Farben von dort abzurufen. Auf diese Weise können das dunkle Design und verschachtelte Designs problemlos unterstützt werden.
Abbildung 2: Das Material-Farbsystem.
Compose bietet die Klasse Colors
zum Modellieren des Farbsystems „Material“. Colors
bietet Builder-Funktionen zum Erstellen von hellen oder dunklen Farben:
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, // ... )
Nachdem Sie die Colors
definiert haben, können Sie sie an eine MaterialTheme
übergeben:
MaterialTheme( colors = if (darkTheme) DarkColors else LightColors ) { // app content }
Designfarben verwenden
Sie können die Colors
, die für die zusammensetzbare Funktion MaterialTheme
bereitgestellt wurde, mit MaterialTheme.colors
abrufen.
Text( text = "Hello theming", color = MaterialTheme.colors.primary )
Oberfläche und Inhaltsfarbe
Viele Komponenten akzeptieren ein Farb- und ein Inhaltsfarbe-Paar:
Surface( color = MaterialTheme.colors.surface, contentColor = contentColorFor(color), // ... ) { /* ... */ } TopAppBar( backgroundColor = MaterialTheme.colors.primarySurface, contentColor = contentColorFor(backgroundColor), // ... ) { /* ... */ }
Auf diese Weise können Sie nicht nur die Farbe einer zusammensetzbaren Funktion festlegen, sondern auch eine Standardfarbe für den Inhalt, also die darin enthaltenen zusammensetzbaren Funktionen, angeben. Bei vielen zusammensetzbaren Funktionen wird diese Inhaltsfarbe standardmäßig verwendet. Beispielsweise basiert die Farbe von Text
auf der Inhaltsfarbe des übergeordneten Elements und Icon
verwendet diese Farbe, um die Färbung festzulegen.
Abbildung 3: Durch das Festlegen verschiedener Hintergrundfarben ergeben sich unterschiedliche Text- und Symbolfarben.
Die Methode contentColorFor()
ruft die entsprechende "on"-Farbe für alle Designfarben ab. Wenn Sie beispielsweise eine Hintergrundfarbe primary
für Surface
festlegen, wird mit dieser Funktion onPrimary
als Inhaltsfarbe festgelegt. Wenn Sie eine Hintergrundfarbe festlegen, die nicht zum Design gehört, sollten Sie auch eine entsprechende Inhaltsfarbe angeben. Verwenden Sie LocalContentColor
, um die bevorzugte Inhaltsfarbe für den aktuellen Hintergrund an einer bestimmten Position in der Hierarchie abzurufen.
Alphaversion für Inhalt
Oftmals sollten Sie variieren, wie sehr Sie Inhalte betonen, um Wichtigkeit zu kommunizieren und eine visuelle Hierarchie zu schaffen. In den Empfehlungen zur Lesbarkeit von Material Design-Texten wird empfohlen, verschiedene Grad der Deckkraft festzulegen, um unterschiedliche Wichtigkeitsstufen zu vermitteln.
Jetpack Compose implementiert dies über LocalContentAlpha
.
Sie können einen Alphawert für Inhalte für eine Hierarchie angeben, indem Sie für diese CompositionLocal
einen Wert angeben.
Verschachtelte zusammensetzbare Funktionen können diesen Wert verwenden, um die Alpha-Behandlung auf ihren Inhalt anzuwenden.
Beispiel: Für Text
und Icon
wird standardmäßig eine Kombination aus LocalContentColor
verwendet, angepasst an LocalContentAlpha
. Material gibt einige Standard-Alphawerte (high
, medium
, disabled
) an, die vom Objekt ContentAlpha
modelliert werden.
// 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( // ... ) }
Weitere Informationen zu CompositionLocal
finden Sie im Leitfaden für lokal zugeordnete Daten im CompositionLocal-Leitfaden.
Abbildung 4: Wenden Sie verschiedene Betonungsebenen auf Text an, um die Informationshierarchie visuell zu vermitteln. Die erste Textzeile ist der Titel und enthält die wichtigsten Informationen. Daher wird ContentAlpha.high
verwendet. Die zweite Zeile enthält weniger wichtige Metadaten und verwendet daher ContentAlpha.medium
.
Dunkles Design
In Compose implementieren Sie helle und dunkle Designs, indem Sie der zusammensetzbaren Funktion MaterialTheme
verschiedene Colors
-Sätze bereitstellen:
@Composable fun MyTheme( darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit ) { MaterialTheme( colors = if (darkTheme) DarkColors else LightColors, /*...*/ content = content ) }
In diesem Beispiel ist MaterialTheme
in eine eigene zusammensetzbare Funktion eingebunden, die einen Parameter akzeptiert, der angibt, ob ein dunkles Design verwendet werden soll. In diesem Fall ruft die Funktion den Standardwert für darkTheme
ab, indem sie die Einstellung des Gerätedesigns abfragt.
Mit einem Code wie diesem können Sie prüfen, ob die aktuellen Colors
hell oder dunkel sind:
val isLightTheme = MaterialTheme.colors.isLight Icon( painterResource( id = if (isLightTheme) { R.drawable.ic_sun_24 } else { R.drawable.ic_moon_24 } ), contentDescription = "Theme" )
Höhen-Overlays
In Material erhalten Oberflächen in dunklen Designs mit höheren Erhebungen Elevation-Overlays, die den Hintergrund aufhellen. Je höher die Höhe einer Oberfläche (d. h., sie nähert sich an eine implizierte Lichtquelle), desto leichter wird sie.
Diese Overlays werden bei Verwendung dunkler Farben automatisch von der zusammensetzbaren Funktion Surface
und allen anderen zusammensetzbaren Funktionen aus Material mit einer Oberfläche angewendet:
Surface( elevation = 2.dp, color = MaterialTheme.colors.surface, // color will be adjusted for elevation /*...*/ ) { /*...*/ }
Abbildung 5: Die Karten und die Navigation unten verwenden beide die Farbe surface
als Hintergrund. Da sich die Karten und die untere Navigationsleiste auf verschiedenen Höhen über dem Hintergrund befinden, haben sie leicht unterschiedliche Farben: Die Karten sind heller als der Hintergrund und die untere Navigationsleiste ist heller als die Karten.
Verwende für benutzerdefinierte Szenarien, die keine Surface
beinhalten, LocalElevationOverlay
, ein CompositionLocal
-Objekt, das die ElevationOverlay
enthält, die von den Surface
-Komponenten verwendet wird:
// 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 )
Zum Deaktivieren von Höhen-Overlays geben Sie null
am gewünschten Punkt in einer zusammensetzbaren Hierarchie an:
MyTheme { CompositionLocalProvider(LocalElevationOverlay provides null) { // Content without elevation overlays } }
Begrenzte Farbakzente
Material empfiehlt, eingeschränkte Farbakzente für dunkle Designs anzuwenden. In den meisten Fällen wird die Farbe surface
gegenüber primary
bevorzugt. Zusammensetzbare Funktionen aus Material wie TopAppBar
und BottomNavigation
implementieren dieses Verhalten standardmäßig.
Abbildung 6: Dunkles Design mit begrenzten Farbakzenten. Für die obere App-Leiste wird die Primärfarbe im hellen Design und die Oberflächenfarbe im dunklen Design verwendet.
Verwenden Sie für benutzerdefinierte Szenarien die Erweiterungseigenschaft primarySurface
:
Surface( // Switches between primary in light theme and surface in dark theme color = MaterialTheme.colors.primarySurface, /*...*/ ) { /*...*/ }
Typografie
Material definiert ein Typsystem, das Ihnen nahelegt, eine kleine Anzahl semantisch benannter Stile zu verwenden.
Abbildung 7: Materialtypsystem.
Compose implementiert das Typsystem mit den Klassen Typography
, TextStyle
und schriftart. Der Typography
-Konstruktor bietet Standardwerte für jeden Stil, sodass Sie alle Stile weglassen können, die Sie nicht anpassen möchten:
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, /*...*/) { /*...*/ }
Wenn Sie überall dieselbe Schriftart verwenden möchten, geben Sie defaultFontFamily parameter
an und lassen Sie fontFamily
aller TextStyle
-Elemente weg:
val typography = Typography(defaultFontFamily = raleway) MaterialTheme(typography = typography, /*...*/) { /*...*/ }
Textstile verwenden
Der Zugriff auf TextStyle
s erfolgt über MaterialTheme.typography
. Rufen Sie die TextStyle
s so ab:
Text( text = "Subtitle2 styled", style = MaterialTheme.typography.subtitle2 )
Abbildung 8: Verwenden Sie verschiedene Schriftarten und Stile, um Ihre Marke auszudrücken.
Form
Material definiert ein Formsystem, in dem Formen für große, mittlere und kleine Komponenten definiert werden können.
Abbildung 9: Das Material-Formsystem.
Compose implementiert das Formsystem mit der Klasse Shapes
, mit der Sie für jede Größenkategorie eine CornerBasedShape
angeben können:
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, /*...*/) { /*...*/ }
Viele Komponenten verwenden diese Formen standardmäßig. Beispiel: Button
, TextField
und FloatingActionButton
sind standardmäßig auf „klein“, AlertDialog
auf „mittel“ und ModalDrawer
auf „groß“. Die vollständige Zuordnung finden Sie in der Referenz zum Formschema.
Formen verwenden
Der Zugriff auf Shape
s erfolgt über MaterialTheme.shapes
. Rufen Sie die Shape
s mit folgendem Code ab:
Surface( shape = MaterialTheme.shapes.medium, /*...*/ ) { /*...*/ }
Abbildung 10: Verwenden Sie Formen, um Marke oder Zustand auszudrücken.
Standardstile
Es gibt kein äquivalentes Konzept bei der Erstellung von Standardformaten aus Android Views. Sie können eine ähnliche Funktionalität bereitstellen, indem Sie Ihre eigenen zusammensetzbaren Überlastfunktionen erstellen, die Material-Komponenten umschließen. Wenn Sie beispielsweise einen Schaltflächenstil erstellen möchten, fügen Sie eine Schaltfläche in Ihre eigene zusammensetzbare Funktion ein, legen Sie die Parameter, die Sie ändern möchten, direkt fest und stellen Sie andere als Parameter für die enthaltene zusammensetzbare Funktion bereit.
@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 ) }
Design-Overlays
Sie können das Äquivalent von Design-Overlays aus Android-Ansichten in der Funktion „Compose“ erreichen, indem Sie zusammensetzbare MaterialTheme
-Objekte verschachteln. Da mit MaterialTheme
die Farben, Typografie und Formen auf den aktuellen Designwert gesetzt werden, behalten die anderen Parameter die Standardwerte bei, wenn bei einem Design nur einer dieser Parameter festgelegt wird.
Achten Sie außerdem bei der Migration von auf Ansichten basierenden Bildschirmen auf die Verwendung des Attributs android:theme
. Sie benötigen wahrscheinlich ein neues MaterialTheme
in diesem Teil des UI-Baums zum Schreiben.
Im Owl-Beispiel wird im Detailbildschirm ein PinkTheme
für den Großteil des Bildschirms und dann ein BlueTheme
für den entsprechenden Abschnitt verwendet. Siehe Screenshot und Code unten.
Abbildung 11: Verschachtelte Designs im Owl-Beispiel.
@Composable fun DetailsScreen(/* ... */) { PinkTheme { // other content RelatedSection() } } @Composable fun RelatedSection(/* ... */) { BlueTheme { // content } }
Komponentenstatus
Materialkomponenten, mit denen interagiert werden kann (angeklickt, ein-/ausgeblendet usw.), können verschiedene visuelle Status haben. Zu den Status gehören „aktiviert“, „deaktiviert“, „betätigt“ usw.
Zusammensetzbare Funktionen haben oft einen enabled
-Parameter. Wenn sie auf false
gesetzt ist, werden Interaktionen verhindert und Eigenschaften wie Farbe und Höhe geändert, um den Komponentenstatus visuell zu vermitteln.
Abbildung 12: Schaltfläche mit enabled = true
(links) und enabled = false
(rechts).
In den meisten Fällen können Sie sich auf Standardwerte wie Werte wie Farbe und Höhe verlassen. Wenn Sie Werte konfigurieren möchten, die in verschiedenen Status verwendet werden, stehen Klassen und praktischen Funktionen zur Verfügung. Hier ein Beispiel für eine Schaltfläche:
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 ) ) { /* ... */ }
Abbildung 13: Schaltfläche mit enabled = true
(links) und enabled = false
(rechts) mit angepassten Farb- und Höhenwerten.
Kleine Wellen
Materialbauteile verwenden Rippchen, um anzuzeigen, mit ihnen zu interagieren. Wenn Sie in Ihrer Hierarchie MaterialTheme
verwenden, wird Ripple
als Standard-Indication
in Modifikatoren wie clickable
und indication
verwendet.
In den meisten Fällen können Sie den standardmäßigen Ripple
verwenden. Wenn Sie die Darstellung konfigurieren möchten, können Sie mit RippleTheme
Eigenschaften wie Farbe und Alpha ändern.
Sie können RippleTheme
erweitern und die Dienstprogrammfunktionen defaultRippleColor
und defaultRippleAlpha
nutzen. Anschließend können Sie mit LocalRippleTheme
ein benutzerdefiniertes Wellenthema in Ihrer Hierarchie angeben:
@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 ) }
Abbildung 14: Schaltflächen mit unterschiedlichen Wellenwerten über RippleTheme
.
Weitere Informationen
Weitere Informationen zu Material Design in Compose finden Sie in den folgenden zusätzlichen Ressourcen.
Codelabs
Videos
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Benutzerdefinierte Designsysteme in Compose
- In Compose von Material 2 zu Material 3 migrieren
- Bedienungshilfen in der Funktion „Compose“