W Jetpack Compose dostępna jest implementacja Material Design, czyli kompleksowego systemu projektowania tworzenie interfejsów cyfrowych. komponenty Material Design (przyciski, karty, przełączniki itp.); opiera się na technologii Material Design, która pozwala systematycznie dostosować styl Material Design, aby lepiej odzwierciedlał markę Twojego produktu. Materiał Motyw zawiera atrybuty color, typografia i kształt. Gdy dostosujesz te zmiany są automatycznie odzwierciedlane w używanych przez Ciebie komponentach aby stworzyć aplikację.
Jetpack Compose wdraża te koncepcje za pomocą komponentu MaterialTheme:
MaterialTheme( colors = // ... typography = // ... shapes = // ... ) { // app content }
Skonfiguruj parametry przekazywane do MaterialTheme, aby stworzyć motyw aplikacji.
Rysunek 1. Pierwszy zrzut ekranu przedstawia aplikację, która nie została skonfigurowana.
MaterialTheme, więc jest w nim używany styl domyślny. Drugi zrzut ekranu pokazuje aplikację, która przekazuje parametry do MaterialTheme w celu dostosowania stylizacji.
Kolor
Kolory są modelowane w komponowaniu za pomocą klasy Color, która jest prostą klasą przechowującą dane.
val Red = Color(0xffff0000) val Blue = Color(red = 0f, green = 0f, blue = 1f)
Możesz je uporządkować w dowolny sposób (jako stałe najwyższego poziomu (pojedynczy lub zdefiniowany w treści) zdecydowanie zalecamy określenie kolorów w z motywu i pobierania kolorów. Takie podejście sprawia, z łatwością obsługi ciemnego motywu i motywów zagnieżdżonych.

Rysunek 2. System kolorów Material
Funkcja tworzenia wiadomości udostępnia Colors
do modelowania
System kolorów Material Design Colors udostępnia funkcje konstruktora do tworzenia zestawów jasnych lub ciemnych kolorów:
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, // ... )
Po zdefiniowaniu Colors możesz je przekazać do MaterialTheme:
MaterialTheme( colors = if (darkTheme) DarkColors else LightColors ) { // app content }
Używanie kolorów motywu
Możesz pobrać Colors przekazane do usługi kompozytowej MaterialTheme, używając MaterialTheme.colors.
Text( text = "Hello theming", color = MaterialTheme.colors.primary )
Kolor powierzchni i treści
Wiele komponentów ma parę kolorów do koloru treści:
Surface( color = MaterialTheme.colors.surface, contentColor = contentColorFor(color), // ... ) { /* ... */ } TopAppBar( backgroundColor = MaterialTheme.colors.primarySurface, contentColor = contentColorFor(backgroundColor), // ... ) { /* ... */ }
Dzięki temu możesz nie tylko ustawić kolor komponenta, ale też określić domyślny kolor treści, czyli komponentów zawartych w danym komponencie. Wiele komponentów używa domyślnie tego koloru treści. Na przykład Text opiera się na
jest do koloru treści elementu nadrzędnego, a Icon używa go do określenia jego
zabarwienie.
Rysunek 3. Ustawienie różnych kolorów tła powoduje zmianę koloru tekstu i ikon.
Metoda contentColorFor()pobiera odpowiedni kolor „włączony” dla dowolnych kolorów motywu. Jeśli na przykład ustawisz kolor tła primary,
w Surface, używa tej funkcji do ustawiania onPrimary jako treści
koloru. Jeśli ustawisz kolor tła niezwiązany z motywem, musisz też określić odpowiedni kolor treści. Użyj formatu LocalContentColor
aby pobrać preferowany kolor treści dla bieżącego tła, na
dane miejsce w hierarchii.
Alfa treści
Często chcesz zróżnicować sposób wyróżniania treści, aby przekazać ich znaczenie i utworzyć hierarchię wizualną. Zalecamy stosowanie różnych poziomów przezroczystości, aby przekazywać różne poziomy ważności.
Jetpack Compose implementuje to za pomocą LocalContentAlpha.
Możesz określić wersję alfa treści w hierarchii, podając wartość
dla: CompositionLocal.
Zawarte w kompozycjach komponenty mogą używać tej wartości, aby zastosować do treści przetwarzanie alfa.
Na przykład Text i Icon domyślnie używają kombinacji LocalContentColor dostosowanych do użycia LocalContentAlpha. Materiał określa niektóre standardowe wartości alfa (high, medium,
disabled), które są modelowane przez obiekt 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( // ... ) }
Aby dowiedzieć się więcej o CompositionLocal, zapoznaj się z lokalnie ograniczonymi danymi w CompositionLocal guide.
Rysunek 4. Stosuj różne poziomy uwydatniania tekstu, aby wizualnie przedstawić
w hierarchii informacji. Pierwszy wiersz tekstu to tytuł, który zawiera najważniejsze informacje, dlatego używa znaku ContentAlpha.high. Druga linia zawiera mniej ważne metadane, dlatego używa ContentAlpha.medium.
Ciemny motyw
W komponowaniu możesz wdrażać motyw jasny i ciemny, przekazując do komponentu Colors różne zestawy:
@Composable fun MyTheme( darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit ) { MaterialTheme( colors = if (darkTheme) DarkColors else LightColors, /*...*/ content = content ) }
W tym przykładzie funkcja MaterialTheme jest ujęta w ramy własnej funkcji składanej, która przyjmuje parametr określający, czy ma być używana ciemna tematyka. W tym przypadku funkcja uzyskuje wartość domyślną dla darkTheme, wysyłając zapytanie do ustawienia motywu urządzenia.
Aby sprawdzić, czy bieżące Colors są jasne czy ciemne, możesz użyć takiego kodu:
val isLightTheme = MaterialTheme.colors.isLight Icon( painterResource( id = if (isLightTheme) { R.drawable.ic_sun_24 } else { R.drawable.ic_moon_24 } ), contentDescription = "Theme" )
Nakładki wysokościowe
W Material Design powierzchnie w ciemnych motywach z wyższymi poziomami mają nakładki wysokości, które rozjaśniają tło. Wyższe wysokość powierzchni (podniesienie jej bliżej) do domniemanego źródła światła), tym jaśniejsza staje się powierzchnia.
Te nakładki są stosowane automatycznie przez funkcję kompozycyjną Surface podczas korzystania z
ciemnych kolorów, a w przypadku innych elementów Material Design, w których jest używana powierzchnia:
Surface( elevation = 2.dp, color = MaterialTheme.colors.surface, // color will be adjusted for elevation /*...*/ ) { /*...*/ }
Rysunek 5. Karty i dolne elementy nawigacyjne mają kolor surface
jako tło. Karty i dolne elementy nawigacyjne różnią się od siebie
poziomy są nieco inne niż w przypadku tła
kolorów – karty są jaśniejsze niż tło, a dolna nawigacja jest
lżejsze od kart.
W przypadku scenariuszy niestandardowych, które nie obejmują Surface, użyj LocalElevationOverlay i CompositionLocal zawierających ElevationOverlay, które są używane przez komponenty 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 )
Aby wyłączyć nakładki wzniesień, podaj null w wybranym punkcie w polu
hierarchia kompozycyjna:
MyTheme { CompositionLocalProvider(LocalElevationOverlay provides null) { // Content without elevation overlays } }
Ograniczone akcenty kolorystyczne
Material Design zaleca stosowanie ograniczonych akcentów kolory w ciemnych tematach. W większości przypadków zaleca się używanie koloru surface zamiast koloru primary. Materiały kompozycyjne Material Design, takie jak TopAppBar i BottomNavigation
zaimplementuj takie działanie domyślnie.

Rysunek 6. Ciemny motyw Material Design z ograniczonymi akcentami kolorystycznymi. Górny pasek aplikacji korzysta z koloru głównego w jasnym motywie, a kolor powierzchni w ciemnym motywie.
W przypadku niestandardowych scenariuszy użyj interfejsu primarySurface
właściwość rozszerzenia:
Surface( // Switches between primary in light theme and surface in dark theme color = MaterialTheme.colors.primarySurface, /*...*/ ) { /*...*/ }
Typografia
Material definiuje system typów, zachęcając do używania niewielkiej liczby stylów o semantycznie nazwach.
Rysunek 7. System typów materiału.
Narzędzie Compose implementuje system typów z klasami Typography, TextStyle i czcionkami. Konstruktor Typography oferuje wartości domyślne dla każdego stylu, więc możesz pominąć te, których nie chcesz dostosowywać:
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, /*...*/) { /*...*/ }
Jeśli chcesz używać tej samej czcionki w całości, określ defaultFontFamily parameter i pominij fontFamily wszystkich elementów TextStyle:
val typography = Typography(defaultFontFamily = raleway) MaterialTheme(typography = typography, /*...*/) { /*...*/ }
Korzystanie ze stylów tekstu
Do TextStyle można uzyskać dostęp przez MaterialTheme.typography. Pobierz
Podobało się to TextStyle osobom:
Text( text = "Subtitle2 styled", style = MaterialTheme.typography.subtitle2 )
Rysunek 8. Wyraź swoją markę, używając różnych krojów i stylów.
Kształt
Materiał definiuje system kształtów, który umożliwia definiowanie kształtów dużych, średnich i małych komponentów.
Rysunek 9. System kształtów Material Design.
Compose wdraża system kształtów za pomocą klasy Shapes, która umożliwia określenie CornerBasedShape dla każdej kategorii rozmiarów:
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, /*...*/) { /*...*/ }
Wiele komponentów domyślnie używa tych kształtów. Na przykład:Button,TextField i FloatingActionButton mają domyślnie rozmiar mały,AlertDialog – średni, a ModalDrawer – duży. Pełną mapę znajdziesz w odniesienie do schematu kształtów.
Korzystanie z kształtów
Elementy Shape są otwierane przez: MaterialTheme.shapes. Odzyskaj Shape za pomocą
podobny do tego:
Surface( shape = MaterialTheme.shapes.medium, /*...*/ ) { /*...*/ }
Rysunek 10. Używaj kształtów do przedstawienia marki lub stanu.
Style domyślne
Nie ma analogicznego pojęcia w funkcji Compose style domyślne w widokach Androida. Możesz zapewnić podobną funkcjonalność, tworząc własne „przeciążone” funkcje kompozycyjne opakowujące komponenty Material. Aby na przykład utworzyć styl przycisku, umieść przycisk we własnej funkcji kompozycyjnej, bezpośrednio ustaw parametry, które chcesz zmienić, i przedstaw inne parametry funkcji kompozycyjnej, która zawiera.
@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 ) }
Nakładki motywu
Możesz uzyskać efekt nakładek motywów z Android Views w Compose, zagnieżdżając komponenty MaterialTheme. Ponieważ
MaterialTheme domyślnie ustawia kolory, typografię i kształty na bieżącą wartość motywu. Jeśli motyw ustawi tylko jeden z tych parametrów, pozostałe parametry zachowają wartości domyślne.
Podczas migracji ekranów opartych na widoku do usługi Compose uważaj na użycie atrybutu android:theme. Prawdopodobnie potrzebny jest nowy
MaterialTheme w tej części drzewa interfejsu tworzenia wiadomości.
W tym przykładzie ekran szczegółów korzysta z PinkTheme na większości ekranu, a potem BlueTheme dla powiązanej sekcji. Poniżej znajdziesz zrzut ekranu i kod.

Rysunek 11. Motywy zagnieżdżone.
@Composable fun DetailsScreen(/* ... */) { PinkTheme { // other content RelatedSection() } } @Composable fun RelatedSection(/* ... */) { BlueTheme { // content } }
Stany komponentu
Komponenty materiału, z którymi można wchodzić w interakcję (klikać, przełączać itp.), mogą mieć różne stany wizualne. Możliwe stany to włączony, wyłączony, wciśnięty itp.
Elementy składane często mają parametr enabled. Ustawienie wartości false uniemożliwia interakcję i zmienia właściwości, takich jak kolor i wysokość, aby wizualnie przekazać stan komponentu.

Rysunek 12. Przycisk z: enabled = true (po lewej) i enabled = false
(po prawej).
W większości przypadków możesz polegać na wartościach domyślnych w przypadku koloru i wysokości. Jeśli chcesz skonfigurować wartości używane w różnych stanach, dostępne są klasy i ułatwienia dostępu. Poniżej znajdziesz przykład przycisku:
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 ) ) { /* ... */ }

Rysunek 13. Przycisk z: enabled = true (po lewej) i enabled = false
(po prawej) z dostosowanymi kolorami i wartościami wysokości.
Kręgi na wodzie
Składniki Material Design używają fal, aby wskazać, że użytkownik wchodzi z nimi w interakcję. Jeśli w hierarchii używasz elementu MaterialTheme, jako domyślny elementIndication w modyfikatorach, takich jak clickable i indication, będzie używany element Ripple.
W większości przypadków możesz polegać na domyślnym Ripple. Konfiguracja
ich wyglądu,
RippleTheme
aby zmienić właściwości, takie jak kolor i alfa.
Możesz rozszerzyć RippleTheme i korzystać z funkcji pomocniczych defaultRippleColor i defaultRippleAlpha. Następnie możesz podać niestandardowy motyw fali w hierarchii za pomocą 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 ) }
Rysunek 14. Przyciski z różnymi wartościami Echo z RippleTheme.
Więcej informacji
Aby dowiedzieć się więcej o motywie Material Design w usłudze Compose, zapoznaj się z tymi artykułami z dodatkowymi zasobami.
Ćwiczenia z programowania
Filmy
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy obsługa JavaScript jest wyłączona
- Niestandardowe systemy projektowania w Compose
- Migracja z wersji Material 2 na wersję Material 3 w komponencie
- Ułatwienia dostępu w sekcji „Tworzenie wiadomości”