Flutter 與 Compose 組件辣么像,難道是同一個google團隊整的;也未深究,只是猜測。
創建項目
需要使用新版本Android studio,忽略步驟…
項目目錄
MainActivity說明
1 系統默認頁面
@Preview 修飾的方法,只用來供開發者預覽使用,刪除不影響運行
@Composable 修飾的方法 只能被@Composable修飾的方法調用
預覽效果
2 MyApplicationTheme 說明
MyApplicationTheme 對應的時 ui.theme 中的Theme.kt中的 MyApplicationTheme ; ctrl+左鍵點過去
下面看代碼
@Composable
fun MyApplicationTheme(darkTheme: Boolean = isSystemInDarkTheme(),// Dynamic color is available on Android 12+dynamicColor: Boolean = true,content: @Composable () -> Unit
) {
咋看這這么像flutter 萬物皆組件嘞;咱也不懂,咱也不敢吭;
- 同樣MyApplicationTheme 是被@Composable注解修飾
darkTheme: Boolean = isSystemInDarkTheme(), //判斷是否是暗黑主題
那么我們把它寫死成ture;
預覽結果 變黑啦
dynamicColor: Boolean = false, //動態顏色
暫未發現有啥變化
代碼里判斷了支持動態顏色,調用了
/*** Creates a light dynamic color scheme.** Use this function to create a color scheme based off the system wallpaper. If the developer* changes the wallpaper this color scheme will change accordingly. This dynamic scheme is a* light theme variant.** @param context The context required to get system resource data.*/
@RequiresApi(Build.VERSION_CODES.S)
fun dynamicLightColorScheme(context: Context): ColorScheme {val tonalPalette = dynamicTonalPalette(context)return lightColorScheme(primary = tonalPalette.primary40,onPrimary = tonalPalette.primary100,primaryContainer = tonalPalette.primary90,onPrimaryContainer = tonalPalette.primary10,inversePrimary = tonalPalette.primary80,secondary = tonalPalette.secondary40,onSecondary = tonalPalette.secondary100,secondaryContainer = tonalPalette.secondary90,onSecondaryContainer = tonalPalette.secondary10,tertiary = tonalPalette.tertiary40,onTertiary = tonalPalette.tertiary100,tertiaryContainer = tonalPalette.tertiary90,onTertiaryContainer = tonalPalette.tertiary10,background = tonalPalette.neutral99,onBackground = tonalPalette.neutral10,surface = tonalPalette.neutral99,onSurface = tonalPalette.neutral10,surfaceVariant = tonalPalette.neutralVariant90,onSurfaceVariant = tonalPalette.neutralVariant30,inverseSurface = tonalPalette.neutral20,inverseOnSurface = tonalPalette.neutral95,outline = tonalPalette.neutralVariant50,)
}
百度翻譯
content: @Composable () -> Unit 頁面布局內容@Composable修飾的組件
content 應該就是Surface,kotlin 最后一個參數如果是lambda表達式,那么lambda表達式可以放在外邊
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {MyApplicationTheme(content = {Surface(modifier = Modifier.fillMaxSize(),color = MaterialTheme.colorScheme.background) {Greeting("Android")}})
}
即
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {MyApplicationTheme(){Surface(modifier = Modifier.fillMaxSize(),color = MaterialTheme.colorScheme.background) {Greeting("Android")}}
}
MyApplicationTheme 方法的實現代碼分析
val colorScheme = when {dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { //這就是動態顏色val context = LocalContext.currentif (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)}darkTheme -> DarkColorSchemeelse -> LightColorScheme}val view = LocalView.current if (!view.isInEditMode) { //這個就是判斷 是否在編輯模式 然后設置了狀態欄的顏色SideEffect {val window = (view.context as Activity).windowwindow.statusBarColor = colorScheme.primary.toArgb()WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme //這一樣也是設置狀態欄的顏色 大概意思就是看翻譯}}MaterialTheme(colorScheme = colorScheme, //設置主題顏色 ui.theme.Colortypography = Typography, // ui.theme.Typecontent = content)
view.isInEditMode 注釋的翻譯
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
通過以上的分析,我們或許可以實現 多主題的功能 用來更改app的主題顏色 字體顯示大小(比如老年模式)等功能 //TODO 后續嘗試
基礎組件
組件一般都包含Modifier的參數
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {Text(text = "Hello $name!",modifier = Modifier.padding())
}
方法參數有個 modifier: Modifier = Modifier ctrl+左鍵 點
發現是Modifier.kt 的對象
// The companion object implements `Modifier` so that it may be used as the start of a// modifier extension factory expression.companion object : Modifier {override fun <R> foldIn(initial: R, operation: (R, Element) -> R): R = initialoverride fun <R> foldOut(initial: R, operation: (Element, R) -> R): R = initialoverride fun any(predicate: (Element) -> Boolean): Boolean = falseoverride fun all(predicate: (Element) -> Boolean): Boolean = trueoverride infix fun then(other: Modifier): Modifier = otheroverride fun toString() = "Modifier"}
使用Modifier都是使用 此伴生對象;是所有鏈式調用的起點
打個斷點看看
例如我們寫了如下代碼
Text(text = "Hello $name!",modifier = Modifier.padding(20.dp))
調用的是Padding.kt的 其實使用的是 PaddingModifier
@Stable
fun Modifier.padding(all: Dp) =this.then(PaddingModifier(start = all,top = all,end = all,bottom = all,rtlAware = true,inspectorInfo = debugInspectorInfo {name = "padding"value = all}))
PaddingModifier 其實實現LayoutModifier
private class PaddingModifier(val start: Dp = 0.dp,val top: Dp = 0.dp,val end: Dp = 0.dp,val bottom: Dp = 0.dp,val rtlAware: Boolean,inspectorInfo: InspectorInfo.() -> Unit
) : LayoutModifier, InspectorValueInfo(inspectorInfo) {
LayoutModifier
@JvmDefaultWithCompatibility
interface LayoutModifier : Modifier.Element {
Modifier.Element
@JvmDefaultWithCompatibilityinterface Element : Modifier {override fun <R> foldIn(initial: R, operation: (R, Element) -> R): R =operation(initial, this)override fun <R> foldOut(initial: R, operation: (Element, R) -> R): R =operation(this, initial)override fun any(predicate: (Element) -> Boolean): Boolean = predicate(this)override fun all(predicate: (Element) -> Boolean): Boolean = predicate(this)}
Modifier 是個接口 實現如下
Modifier 可用來設置形狀,大小,位置,邊距,透明度,點擊 等
例如 Text的modifier可以設置如下
modifier = Modifier.padding()
Padding.kt Modifer的擴展方法
Text 文本
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {Text(text = "Hello $name!",modifier = modifier)
}
Image 圖片
Image(painter = painterResource(id = R.drawable.img_lufei), //資源contentDescription = "", //描述modifier = Modifier.size(80.dp).clip(CircleShape), //大小 形狀contentScale = ContentScale.Crop //渲染方式)
Spacer 空白
Text(text = "Hello $name!")Spacer(modifier = Modifier.padding(20.dp))Text(text = "Hello llo lo $name!")
Column 橫布局
Column(modifier = Modifier.padding(10.dp)) {Text(text = "Hello $name!")Spacer(modifier = Modifier.padding(20.dp))Text(text = "Hello llo lo $name!")}
Row 豎布局
Row(modifier = Modifier.wrapContentHeight(align = Alignment.CenterVertically)) {Image(painter = painterResource(id = R.drawable.img_lufei),contentDescription = "",modifier = Modifier.size(80.dp).clip(CircleShape),contentScale = ContentScale.Crop)Column(modifier = Modifier.padding(10.dp)) {Text(text = "Hello $name!")Spacer(modifier = Modifier.padding(20.dp))Text(text = "Hello llo lo $name!")}}
效果
其他布局用到時詳解
接下來的問題
- 布局的對齊方式 在父布局中的位置 父布局控制子布局的位置