Material, önerdiğimiz tasarım sistemi olsa ve Jetpack Compose, Material'ın bir uygulamasını içerse de bu sistemi kullanmak zorunda değilsiniz. Material tamamen herkese açık API'ler üzerine kurulduğundan aynı şekilde kendi tasarım sisteminizi oluşturabilirsiniz.
Bu konuda birkaç yaklaşım izleyebilirsiniz:
- Ek temalandırma değerleriyle
MaterialTheme
'ı genişletme - Bir veya daha fazla Material sistemini (
Colors
,Typography
veyaShapes
) diğerlerini koruyarak özel uygulamalarla değiştirme MaterialTheme
yerine tamamen özel bir tasarım sistemi uygulama
Ayrıca, özel tasarım sistemine sahip Material bileşenlerini kullanmaya devam etmek isteyebilirsiniz. Bu işlemi yapmanız mümkündür ancak seçtiğiniz yaklaşıma uygun olması için dikkat etmeniz gereken noktalar vardır.
MaterialTheme
ve özel tasarım sistemleri tarafından kullanılan daha düşük seviyeli yapıları ve API'ler hakkında daha fazla bilgi edinmek için Compose'da temanın yapısı rehberine göz atın.
Materyal temasını genişletme
Compose Material, Material Temalandırma'yı yakından örnek alarak Material kurallarına uymayı basit ve tür açısından güvenli hale getirir. Ancak renk, tipografi ve şekil kümelerini ek değerlerle genişletmek mümkündür.
En basit yaklaşım, uzantı özellikleri eklemektir:
// Use with MaterialTheme.colorScheme.snackbarAction val ColorScheme.snackbarAction: Color @Composable get() = if (isSystemInDarkTheme()) Red300 else Red700 // Use with MaterialTheme.typography.textFieldInput val Typography.textFieldInput: TextStyle get() = TextStyle(/* ... */) // Use with MaterialTheme.shapes.card val Shapes.card: Shape get() = RoundedCornerShape(size = 20.dp)
Bu, MaterialTheme
kullanım API'leriyle tutarlılık sağlar. Compose'un kendisi tarafından tanımlanan bu duruma bir örnek, yüksekliğe bağlı olarak kullanılması gereken yüzey rengini belirleyen surfaceColorAtElevation
'dir.
Başka bir yaklaşım da MaterialTheme
ve değerlerini "saran" genişletilmiş bir tema tanımlamaktır.
Mevcut Material renklerini korurken caution
ve onCaution
olmak üzere iki renk daha eklemek istediğinizi varsayalım. caution
, yarı tehlikeli işlemler için kullanılan sarı bir renktir.
@Immutable data class ExtendedColors( val caution: Color, val onCaution: Color ) val LocalExtendedColors = staticCompositionLocalOf { ExtendedColors( caution = Color.Unspecified, onCaution = Color.Unspecified ) } @Composable fun ExtendedTheme( /* ... */ content: @Composable () -> Unit ) { val extendedColors = ExtendedColors( caution = Color(0xFFFFCC02), onCaution = Color(0xFF2C2D30) ) CompositionLocalProvider(LocalExtendedColors provides extendedColors) { MaterialTheme( /* colors = ..., typography = ..., shapes = ... */ content = content ) } } // Use with eg. ExtendedTheme.colors.caution object ExtendedTheme { val colors: ExtendedColors @Composable get() = LocalExtendedColors.current }
Bu, MaterialTheme
kullanım API'lerine benzer. Ayrıca, ExtendedTheme
öğelerini MaterialTheme
öğeleriyle aynı şekilde iç içe yerleştirebileceğiniz için birden fazla temayı da destekler.
Material bileşenlerini kullanma
Material Teması'nı genişletirken mevcut MaterialTheme
değerleri korunur ve Material bileşenleri yine de makul varsayılan değerlere sahip olur.
Bileşenlerde genişletilmiş değerler kullanmak istiyorsanız bunları kendi composable işlevlerinize sarmalayın, değiştirmek istediğiniz değerleri doğrudan ayarlayın ve diğerlerini kapsayan composable'a parametre olarak sunun:
@Composable fun ExtendedButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( containerColor = ExtendedTheme.colors.caution, contentColor = ExtendedTheme.colors.onCaution /* Other colors use values from MaterialTheme */ ), onClick = onClick, modifier = modifier, content = content ) }
Ardından, uygun yerlerde Button
kullanımlarını ExtendedButton
ile değiştirirsiniz.
@Composable fun ExtendedApp() { ExtendedTheme { /*...*/ ExtendedButton(onClick = { /* ... */ }) { /* ... */ } } }
Malzeme alt sistemlerini değiştirme
Material Theming'i genişletmek yerine, diğerlerini korurken Colors
, Typography
veya Shapes
gibi bir veya daha fazla sistemi özel bir uygulamayla değiştirmek isteyebilirsiniz.
Renk sistemini korurken tür ve şekil sistemlerini değiştirmek istediğinizi varsayalım:
@Immutable data class ReplacementTypography( val body: TextStyle, val title: TextStyle ) @Immutable data class ReplacementShapes( val component: Shape, val surface: Shape ) val LocalReplacementTypography = staticCompositionLocalOf { ReplacementTypography( body = TextStyle.Default, title = TextStyle.Default ) } val LocalReplacementShapes = staticCompositionLocalOf { ReplacementShapes( component = RoundedCornerShape(ZeroCornerSize), surface = RoundedCornerShape(ZeroCornerSize) ) } @Composable fun ReplacementTheme( /* ... */ content: @Composable () -> Unit ) { val replacementTypography = ReplacementTypography( body = TextStyle(fontSize = 16.sp), title = TextStyle(fontSize = 32.sp) ) val replacementShapes = ReplacementShapes( component = RoundedCornerShape(percent = 50), surface = RoundedCornerShape(size = 40.dp) ) CompositionLocalProvider( LocalReplacementTypography provides replacementTypography, LocalReplacementShapes provides replacementShapes ) { MaterialTheme( /* colors = ... */ content = content ) } } // Use with eg. ReplacementTheme.typography.body object ReplacementTheme { val typography: ReplacementTypography @Composable get() = LocalReplacementTypography.current val shapes: ReplacementShapes @Composable get() = LocalReplacementShapes.current }
Material bileşenlerini kullanma
MaterialTheme
sistemlerinden biri veya daha fazlası değiştirildiğinde, Material bileşenlerini olduğu gibi kullanmak istenmeyen Material rengi, türü veya şekil değerlerine neden olabilir.
Bileşenlerde değiştirme değerleri kullanmak istiyorsanız bunları kendi composable işlevlerinize sarmalayın, ilgili sistemin değerlerini doğrudan ayarlayın ve diğerlerini kapsayan composable'a parametre olarak sunun.
@Composable fun ReplacementButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( shape = ReplacementTheme.shapes.component, onClick = onClick, modifier = modifier, content = { ProvideTextStyle( value = ReplacementTheme.typography.body ) { content() } } ) }
Ardından, uygun yerlerde Button
kullanımlarını ReplacementButton
ile değiştirirsiniz.
@Composable fun ReplacementApp() { ReplacementTheme { /*...*/ ReplacementButton(onClick = { /* ... */ }) { /* ... */ } } }
Tamamen özel bir tasarım sistemi uygulama
Material Theming'i tamamen özel bir tasarım sistemiyle değiştirmek isteyebilirsiniz.
MaterialTheme
'nın aşağıdaki sistemleri sağladığını düşünün:
Colors
,Typography
veShapes
: Materyal Teması Oluşturma sistemleriTextSelectionColors
:Text
veTextField
tarafından metin seçimi için kullanılan renklerRipple
veRippleTheme
:Indication
'ın materyal olarak uygulanması
Material bileşenlerini kullanmaya devam etmek istiyorsanız özel temanızda veya temalarınızda bu sistemlerden bazılarını değiştirmeniz ya da istenmeyen davranışları önlemek için bileşenlerinizdeki sistemleri yönetmeniz gerekir.
Ancak tasarım sistemleri, Material'ın dayandığı kavramlarla sınırlı değildir. Diğer kavramları temalarla uyumlu hale getirmek için mevcut sistemleri değiştirebilir ve tamamen yeni sistemler (yeni sınıflar ve türlerle) oluşturabilirsiniz.
Aşağıdaki kodda, gradyanlar (List<Color>
) içeren özel bir renk sistemi oluşturuyoruz, bir tür sistemi ekliyoruz, yeni bir yükseklik sistemi sunuyoruz ve MaterialTheme
tarafından sağlanan diğer sistemleri hariç tutuyoruz:
@Immutable data class CustomColors( val content: Color, val component: Color, val background: List<Color> ) @Immutable data class CustomTypography( val body: TextStyle, val title: TextStyle ) @Immutable data class CustomElevation( val default: Dp, val pressed: Dp ) val LocalCustomColors = staticCompositionLocalOf { CustomColors( content = Color.Unspecified, component = Color.Unspecified, background = emptyList() ) } val LocalCustomTypography = staticCompositionLocalOf { CustomTypography( body = TextStyle.Default, title = TextStyle.Default ) } val LocalCustomElevation = staticCompositionLocalOf { CustomElevation( default = Dp.Unspecified, pressed = Dp.Unspecified ) } @Composable fun CustomTheme( /* ... */ content: @Composable () -> Unit ) { val customColors = CustomColors( content = Color(0xFFDD0D3C), component = Color(0xFFC20029), background = listOf(Color.White, Color(0xFFF8BBD0)) ) val customTypography = CustomTypography( body = TextStyle(fontSize = 16.sp), title = TextStyle(fontSize = 32.sp) ) val customElevation = CustomElevation( default = 4.dp, pressed = 8.dp ) CompositionLocalProvider( LocalCustomColors provides customColors, LocalCustomTypography provides customTypography, LocalCustomElevation provides customElevation, content = content ) } // Use with eg. CustomTheme.elevation.small object CustomTheme { val colors: CustomColors @Composable get() = LocalCustomColors.current val typography: CustomTypography @Composable get() = LocalCustomTypography.current val elevation: CustomElevation @Composable get() = LocalCustomElevation.current }
Material bileşenlerini kullanma
MaterialTheme
bulunmadığında, Material bileşenlerinin olduğu gibi kullanılması istenmeyen Material rengi, türü ve şekil değerlerine ve gösterge davranışına neden olur.
Bileşenlerde özel değerler kullanmak istiyorsanız bunları kendi composable işlevlerinize sarmalayın, ilgili sistemin değerlerini doğrudan ayarlayın ve diğerlerini içeren composable'a parametre olarak sunun.
Belirlediğiniz değerlere özel temanızdan erişmenizi öneririz.
Alternatif olarak, temanız Color
, TextStyle
, Shape
veya diğer sistemleri sağlamıyorsa bunları sabit kodlayabilirsiniz.
@Composable fun CustomButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( containerColor = CustomTheme.colors.component, contentColor = CustomTheme.colors.content, disabledContainerColor = CustomTheme.colors.content .copy(alpha = 0.12f) .compositeOver(CustomTheme.colors.component), disabledContentColor = CustomTheme.colors.content .copy(alpha = 0.38f) ), shape = ButtonShape, elevation = ButtonDefaults.elevatedButtonElevation( defaultElevation = CustomTheme.elevation.default, pressedElevation = CustomTheme.elevation.pressed /* disabledElevation = 0.dp */ ), onClick = onClick, modifier = modifier, content = { ProvideTextStyle( value = CustomTheme.typography.body ) { content() } } ) } val ButtonShape = RoundedCornerShape(percent = 50)
List<Color>
gibi yeni sınıf türleri eklediyseniz bunları sarmalamak yerine bileşenleri sıfırdan uygulamak daha iyi olabilir. Örnek olarak, Jetsnack örneğindeki
JetsnackButton
öğesine göz atın.
Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir.
- Compose'da Material Design 3
- Oluşturma'da Material 2'den Material 3'e geçiş
- Compose'daki temanın anatomisi