Ada beberapa cara untuk membuat aplikasi menggunakan Gaya. Pilihan Anda bergantung pada posisi aplikasi Anda dalam kaitannya dengan penerapan Desain Material:
- Sistem desain yang sepenuhnya kustom, tidak menggunakan Desain Material
- Rekomendasi: Tentukan gaya komponen yang menggunakan nilai dari tema, dan tampilkan parameter gaya pada komponen sistem desain.
- Menggunakan Desain Material
- Rekomendasi: Tunggu penerapan Material untuk berintegrasi dengan Gaya. Gunakan gaya pada komponen Anda sendiri jika memungkinkan.
Lapisan Gaya
Dalam model Compose tradisional, penyesuaian sering kali sangat bergantung pada penggantian token global (warna dan tipografi) yang disediakan oleh MaterialTheme, atau menggabungkan dan mengganti properti composable sistem desain jika memungkinkan.
Terkadang, ada properti dalam lapisan Material yang tidak ditampilkan melalui subsistem atau parameter, tetapi merupakan default hardcode pada komponen itu sendiri.
Dengan Styles API, ada lapisan abstraksi baru yang menjadi jembatan antara subsistem dan komponen: Gaya.
| Lapisan | Tanggung jawab | Contoh |
|---|---|---|
| Nilai subsistem | Nilai bernama | val Primary = Color(0xFF34A85E) |
| Gaya Atom | Gaya yang hanya melakukan satu perubahan properti | val buttonStyle = paddingAtomic then roundedCornerShapeAtomic then primaryBackgroundAtomic then largeSize then interactiveShadowAtomic |
| Gaya Komponen | Konfigurasi khusus komponen | Tombol dengan latar belakang Utama dan padding 16 dp. val buttonStyle = Style { contentPadding(16.dp) shape(RoundedCornerShape(8.dp)) background(Color.Blue) } |
| Komponen | Elemen UI fungsional yang menggunakan Gaya. | Button(style = buttonStyle) { ... } |
Gaya atom versus monolitik
Dengan Styles API, Anda dapat membagi Gaya menjadi gaya atom terpisah.
Selain menentukan gaya khusus komponen yang kompleks seperti baseButtonStyle, Anda juga dapat membuat gaya utilitas kecil dan sekali pakai. Gaya ini bertindak sebagai "atom" Anda.
// Define single-purpose "atomic" styles val paddingAtomic = Style { contentPadding(16.dp) } val roundedCornerShapeAtomic = Style { shape(RoundedCornerShape(8.dp)) } val primaryBackgroundAtomic = Style { background(Color.Blue) } val largeSizeAtomic = Style { size(100.dp, 40.dp) } val interactiveShadowAtomic = Style { hovered { animate { dropShadow( Shadow( offset = DpOffset( 0.dp, 0.dp ), radius = 2.dp, spread = 0.dp, color = Color.Blue, ) ) } } }
Komposisi menggunakan "then"
Salah satu fitur canggih dari Styles API baru adalah operator then, yang memungkinkan Anda menggabungkan beberapa objek Style. Hal ini memungkinkan Anda membuat komponen menggunakan class utilitas atom.
Tradisional (non-atom):
// One large monolithic style val buttonStyle = Style { contentPadding(16.dp) shape(RoundedCornerShape(8.dp)) background(Color.Blue) }
Refaktor atom:
// Combine atoms to create the final appearance val buttonStyle = paddingAtomic then roundedCornerShapeAtomic then primaryBackgroundAtomic then interactiveShadowAtomic
Menggunakan Gaya dalam sistem desain Anda
Pertimbangkan opsi berikut saat menggunakan Gaya dalam sistem desain Anda, bergantung pada posisi sistem desain Anda dalam spektrum.
Sistem desain kustom dengan Gaya
Pertimbangkan kapan: Anda telah menerima panduan merek yang luas dan tidak didasarkan pada Desain Material, dan Anda tidak berencana menggunakan Desain Material.
Strategi: Terapkan sistem desain yang sepenuhnya kustom, dan tampilkan gaya sebagai bagian dari tema.
Opsi ini adalah jalur kustom jika Anda tidak menggunakan Material sebagai bahasa sistem desain utama. Anda sepenuhnya melewati MaterialTheme untuk definisi visual dan
telah membuat tema kustom Anda sendiri. Anda membuat CompanyTheme yang bertindak sebagai penampung untuk Gaya Anda.
- Cara kerjanya: Buat objek
CompanyThemeyang menyimpan objekStyleuntuk setiap komponen dalam sistem Anda. Komponen Anda (baik wrapper di sekitar logika Material atau implementasiBoxatauLayoutkustom) menggunakan gaya ini secara langsung, dan menampilkan parameterStyleuntuk konsumen sistem desain Anda. - Lapisan Gaya: Gaya adalah definisi utama sistem desain Anda. Token adalah variabel bernama yang dimasukkan ke dalam gaya ini. Hal ini memungkinkan penyesuaian mendalam, seperti menentukan animasi unik untuk perubahan status (misalnya, menganimasikan skala dan warna saat ditekan).
Jika Anda membuat tema kustom sendiri tanpa menggunakan Material, dan ingin menggunakan gaya, tambahkan daftar gaya ke Tema Anda. Hal ini memungkinkan Anda mengakses gaya dasar dari mana saja di project Anda.
Buat class
Stylesyang menyimpan berbagai gaya di aplikasi Anda dan buat default. Misalnya, di aplikasi Jetsnack, class diberi namaJetsnackStyles:object JetsnackStyles{ val buttonStyle: Style = Style { shape(shapes.medium) background(colors.brand) contentColor(colors.textPrimary) contentPaddingVertical(8.dp) contentPaddingHorizontal(24.dp) textStyle(typography.labelLarge) disabled { animate { background(colors.brandSecondary) } } } val cardStyle: Style = Style { shape(shapes.medium) background(colors.uiBackground) contentColor(colors.textPrimary) } }
Berikan
Stylessebagai bagian dari tema keseluruhan Anda, dan tampilkan fungsi ekstensi helper diStyleScopeuntuk mengakses subsistem:@Immutable class JetsnackTheme( val colors: JetsnackColors = LightJetsnackColors, val typography: androidx.compose.material3.Typography = androidx.compose.material3.Typography(), val shapes: Shapes = Shapes() ) { companion object { val colors: JetsnackColors @Composable @ReadOnlyComposable get() = LocalJetsnackTheme.current.colors val typography: androidx.compose.material3.Typography @Composable @ReadOnlyComposable get() = LocalJetsnackTheme.current.typography val shapes: Shapes @Composable @ReadOnlyComposable get() = LocalJetsnackTheme.current.shapes val styles: JetsnackStyles = JetsnackStyles val LocalJetsnackTheme: ProvidableCompositionLocal<JetsnackTheme> get() = LocalJetsnackThemeInstance } } val StyleScope.colors: JetsnackColors get() = LocalJetsnackTheme.currentValue.colors val StyleScope.typography: androidx.compose.material3.Typography get() = LocalJetsnackTheme.currentValue.typography val StyleScope.shapes: Shapes get() = LocalJetsnackTheme.currentValue.shapes internal val LocalJetsnackThemeInstance = staticCompositionLocalOf { JetsnackTheme() } @Composable fun JetsnackTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) { val colors = if (darkTheme) DarkJetsnackColors else LightJetsnackColors val theme = JetsnackTheme(colors = colors) CompositionLocalProvider( LocalJetsnackTheme provides theme, ) { MaterialTheme( typography = LocalJetsnackTheme.current.typography, shapes = LocalJetsnackTheme.current.shapes, content = content, ) } }
Akses
JetsnackStylesdalam composable Anda:@Composable fun CustomButton(modifier: Modifier, style: Style = Style, text: String) { val interactionSource = remember { MutableInteractionSource() } val styleState = remember(interactionSource) { MutableStyleState(interactionSource) } // Apply style to top level container in combination with incoming style from parameter. Box(modifier = modifier .clickable( interactionSource = interactionSource, indication = null, enabled = true, role = Role.Button, onClick = { }, ) .styleable(styleState, JetsnackTheme.styles.buttonStyle, style)) { Text(text) } }
Selain penggunaan tema global, ada strategi alternatif untuk menggabungkan Styles ke dalam aplikasi Anda. Anda dapat memanfaatkan Styles secara inline untuk situs panggilan tertentu atau menggunakan definisi statis jika kemampuan tema penuh tidak diperlukan.
Styles tidak boleh ditukar secara kondisional kecuali jika seluruh gaya pada dasarnya berbeda. Anda sebaiknya mengakses token dinamis di dalam definisi visual daripada beralih di antara objek gaya yang berbeda.