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”