今天大概會聊到的範圍
- Theme
透過 Android Studio 內建的精靈建立一個新的 Compose 專案或是建立新的 "Empty Compose Activity" 時,會發現這樣的 code :
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ProjectNameTheme { // <--- 今天主角
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
Greeting("Android")
}
}
}
}
}
可以發現預設的 Code 會在內容的 Composable 之外,再包一個 Theme。仔細研究一下這個 Theme。這個 Theme 通常是開啟新的 Compose 專案時自動建立的。可以觀察到這個 Theme 其實是對 MaterialTheme 的包裝。
@Composable
fun ProjectNameTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
在 MaterialTheme 中,要提供 color 、typography、shapes。
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
在 Android Studio 自動建立的 Theme 中,會判斷是否是 dark mode,在不同的情況下使用不同的 "ColorPalette"
Color Palette 是 Material Design 中重要的概念。透過一組事先配好的顏色讓整個 App 的顏色有一致性。要提供 MaterialTheme color,我們要提供的 Colors 物件時就需要提供這個 Palette 中所需要的各個顏色:
class Colors(
primary: Color,
primaryVariant: Color,
secondary: Color,
secondaryVariant: Color,
background: Color,
surface: Color,
error: Color,
onPrimary: Color,
onSecondary: Color,
onBackground: Color,
onSurface: Color,
onError: Color,
isLight: Boolean // 是否是 dark mode
)
除了顏色之外,typography 可以定義 h1 ~ body 等不同字級。可以參考 Material Design 的 Type System 、另外還有 Shape System 可以設定在不同的情況下物件的形狀。
Theme 已經配置好了,我們也將 content 包在 Theme 裡面了,那要怎麼取得我們 Theme 的配置呢?
@Composable
fun UIComposable() {
MaterialTheme() {
Card(modifier = Modifier.background(MaterialTheme.colors.background)) {
// ...
}
}
}
我們只需要透過 MaterialTheme.(colors | typography | shapes)
就可以取得對應的參數了!
在 Compose 中,使用 Theme 真的非常的簡單,設定的地方和使用的地方都非常直覺。很好奇 Compose framework 實際上怎麼做到這件事的? 也許可以當成後續的主題吧!
Reference: