環(huán)境配置
首先在 Module 的 build.gradle.kts
文件中添加 compose 的依賴(lài)
plugins {
kotlin("multiplatform")
id("com.android.library")
// 添加 compose 插件河质,
// 這里為什么是 1.5.10,以為我使用的是 1.9.20 的 Kotlin
// Kotlin 和 Compose 的版本對(duì)應(yīng)關(guān)系可見(jiàn)文末鏈接
id("org.jetbrains.compose").version("1.5.10")
}
sourceSets {
val commonMain by getting {
dependencies {
// compose
api(compose.ui)
api(compose.foundation)
api(compose.material)
api(compose.runtime)
}
}
}
添加完畢后染坯,sync 一下,提示需要將 compileSdkVersion
升級(jí)到 33丘逸,修改根目錄下的 build.gradle
ext {
compileSdkVersion = 33
}
再次 sync单鹿,提示錯(cuò)誤警告:uikit還處于試驗(yàn)階段并且有許多bug,想要使用的話(huà)深纲,需要在 gradle.properties
添加一個(gè)配置項(xiàng)
##ERROR: Compose targets '[uikit]' are experimental and may have bugs!
##But, if you still want to use them, add to gradle.properties:
org.jetbrains.compose.experimental.uikit.enabled=true
至此仲锄,可以開(kāi)始嘗試使用 Compose 了
使用ComposeUI寫(xiě)界面
寫(xiě)了一個(gè)常見(jiàn)的列表分組樣式,更多 Compose 用法這里不做演示
// 必須添加這個(gè)注解
@Composable
fun AboutUsView(response: String, onItemClick: () -> Unit) {
// 解析出列表數(shù)據(jù)
val list = json.decodeFromString<List<AboutGroupItemBean>>(response)
// 創(chuàng)建一個(gè)縱向布局
Column {
// LazyColumn 類(lèi)比 ListView
LazyColumn {
// 遍歷添加數(shù)據(jù)
list.forEach { group ->
// 添加一個(gè)組數(shù)據(jù)湃鹊,這里寫(xiě)的是一個(gè)分割線(xiàn)
item {
// 自定義的 Composable 函數(shù)
SHDivider()
}
val groupItem = group.groupItem
groupItem?.let {
// 繼續(xù)遍歷 group 中的列表數(shù)據(jù)
itemsIndexed(it) { index, item ->
Column {
// 只有非第一行數(shù)據(jù)儒喊,才有分割線(xiàn)
if (index != 0) {
SHDivider(1.dp)
}
val title = item["title"]
// 單條數(shù)據(jù)
SHListItem(title, onItemClick)
}
}
}
}
}
}
}
// 自定義的分割線(xiàn)
@Composable
fun SHDivider(height: Dp = 10.dp) {
Divider(
modifier = Modifier.height(height),
color = Color(0xFFFAFAFB)
)
}
// 自定義的列表數(shù)據(jù)
@Composable
fun SHListItem(title: String?, onItemClick: () -> Unit) {
if (!title.isNullOrEmpty()) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(44.dp)
.clickable(onClick = onItemClick)
.background(Color.White),
contentAlignment = Alignment.CenterStart
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxWidth()
) {
Text(
text = title,
fontSize = 14.sp,
color = Color(0xFF333333),
modifier = Modifier.padding(start = 15.dp)
)
Text(
text = "箭頭",
modifier = Modifier.padding(end = 15.dp)
)
}
}
}
}
遇到的問(wèn)題
加載本地圖片
使用 Compose 加載本地圖片代碼如下
Image(
painter = painterResource(res: String),
contentDescription = null,
)
但是上述導(dǎo)入的依賴(lài)庫(kù)中并沒(méi)有 painterResource
函數(shù),故需要添加新的依賴(lài)币呵,代碼如下
sourceSets {
val commonMain by getting {
dependencies {
...
// 解決 compose-ui 資源加載問(wèn)題
@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
implementation(compose.components.resources)
}
}
}
這里有個(gè)問(wèn)題澄惊,compose.components.resources
接入時(shí),需要添加 @OptIn
注解,注解的意思為:這是一個(gè)試驗(yàn)中的庫(kù)掸驱,說(shuō)明還不能用在生產(chǎn)包中肛搬,只能用于嘗鮮
看了 painterResource 的源碼,也有著大大 TODO 注釋?zhuān)f(shuō)未來(lái)這個(gè) API 會(huì)改變毕贼。
解決方案
在這個(gè)資源庫(kù)穩(wěn)定之前温赔,其實(shí)也是有其他解決方案的,一個(gè)是使用第三方資源庫(kù)鬼癣,另一個(gè)是使用 expect/actual
進(jìn)行平臺(tái)化實(shí)現(xiàn)(有點(diǎn)麻煩陶贼,且不合理)。
iOS 平臺(tái) JSON 序列化失敗
JSON 字符串轉(zhuǎn) ViewModel待秃,一個(gè)很常見(jiàn)的需求拜秧,在 KMM 中如何使用呢?可以使用 kotlinx-serialization-json
章郁,它是一個(gè)支持跨平臺(tái)的序列化庫(kù)
plugins {
// 添加插件
kotlin("plugin.serialization").version("1.9.20")
}
sourceSets {
val commonMain by getting {
dependencies {
// Kotlin Json 解析
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.1")
}
}
}
用法可以參考:kotlinx-serialization-json - GitHub
下方這段代碼在 Android 平臺(tái)上是可以正常使用的枉氮,但是在 iOS 平臺(tái)上閃退了,目前還沒(méi)有定位到原因暖庄。
val list = json.decodeFromString<List<AboutGroupItemBean>>(response)