前语

Compose是Android官方供给的声明式UI开发结构,而Compose Multiplatform是由JetBrains 维护的,关于Android开发来说,个人认为学习Jetpack Compose是有必要的,由于它会成为Android主流的开发模式,而compose-jb作为一个扩展能力,咱们能够有挑选的去测验。今天咱们先来了解一下运用compose-jb开发一个桌面端应用的流程。

接下来还会有第二弹,第三弹…

环境要求

开发Compose for Desktop环境要求主要有两点:

  • JDK 11或更高版别

  • IntelliJ IDEA 2020.3 或更高版别(也能够运用AS,这儿为了运用IDEA供给的项目模板)

接着咱们来一步步体验Compose for Desktop的开发流程。

开发流程

创立项目

下载好IDEA后,咱们直接新建项目,挑选Compose Multipalteform类型,输入项目名称,这儿只挑选Single platform且平台为Desktop即可。

Compose跨平台第一弹:体验Compose for Desktop

创立好项目后,来看项目目录结构,目录结构如下图所示。

Compose跨平台第一弹:体验Compose for Desktop

在配置文件中指定了程序入口为MainKt以及包名、版别号等。MainKt文件代码如下所示。

@Composable
@Preview
fun App() {
    var text by remember { mutableStateOf("Hello, World!") }
    MaterialTheme {
        Button(onClick = {
            text = "Hello, Desktop!"
        }) {
            Text(text)
        }
    }
}
fun main() = application {
    Window(onCloseRequest = ::exitApplication) {
        App()
    }
}

在MainKt文件中,入口处调用了App()办法,App办法中绘制了一个按钮,运转程序,结果如下图所示。

Compose跨平台第一弹:体验Compose for Desktop

咱们能够看到一个Hello World的桌面端程序就显示出来了。接下来咱们来增加一些页面元素。

增加输入框

为了让桌面端程序更“像姿态”,咱们首要修改桌面程序的标题为“学生管理体系”,这毕竟是咱们学生时代最喜欢的姓名。代码如下所示:

fun main() = application {
    Window(onCloseRequest = ::exitApplication, title = "学生管理体系") {
        App()
    }
}

在App办法中,增加两个输入框别离为学号、暗码,增加一个登陆按钮,写法与Android中的Compose共同,代码如下所示。

MaterialTheme {
    var name by remember {
        mutableStateOf("")
    }
    var password by remember {
        mutableStateOf("")
    }
    Column {
        TextField(name, onValueChange = {
            name = it
        }, placeholder = {
            Text("请输入学号")
        })
        TextField(password, onValueChange = {
            password = it
        }, placeholder = {
            Text("请输入暗码")
        })
        Button(onClick = {
        }) {
            Text("登陆")
        }
    }
}

再次运转程序,页面如下所示。

Compose跨平台第一弹:体验Compose for Desktop

增加头像

接着咱们再来增加头像显示,咱们将下载好的图片资源放在resources目录下

Compose跨平台第一弹:体验Compose for Desktop

然后运用Image组件将头像显示出来即可,代码如下所示。

Image(
    painter = painterResource("photo.png"),
    contentDescription = null,
    modifier = Modifier.size(width = 100.dp, height = 100.dp)
        .clip(CircleShape)
)

再次运转程序,结果如下所示。

Compose跨平台第一弹:体验Compose for Desktop

当然咱们还能够将布局略微修饰一下,使得布局看起来更美观一些。但这并不是这儿的重点。

增加退出弹窗

当咱们点击左上角(macOS)的X号时,应用程序就直接退出了,这是由于在Window函数中指定了退出事件,再来看一下这部分代码,如下所示。

fun main() = application {
    Window(onCloseRequest = ::exitApplication, title = "学生管理体系") {
        App()
    }
}

接下来咱们增加一个承认退出的弹窗提示。代码如下所示。

fun main() = application {
    var windowsOpen by remember {
        mutableStateOf(true)
    }
    var isClose by remember {
        mutableStateOf(false)
    }
    if (windowsOpen) {
        Window(onCloseRequest = { isClose = true }, title = "学生管理体系") {
            App()
            if (isClose) {
                Dialog(onCloseRequest = { isClose = false }, title = "确定退出应用程序吗?") {
                    Row {
                        Button(onClick = {
                            windowsOpen = false
                        }) {
                            Text("确定")
                        }
                    }
                }
            }
        }
    }
}

这儿咱们新增了两个变量windowsOpen、isClose别离用来控制应用程序的Window是否显示与承认弹窗的显示。这部分代码相信运用过Jetpack Compose的都能够看得懂。

运转程序,点击X号,弹出退出承认弹窗,点击确定,应用程序将退出。作用如下图所示。

Compose跨平台第一弹:体验Compose for Desktop

完成一个网络恳求功用

在 KMM入门 中咱们借用「wanandroid」中「每日一问」接口完成了一个网络恳求,现在咱们将这部分功用移植到Desktop程序中,网络恳求结构仍然运用Ktor,当然其实你也能够运用Retrofit,这一点并不重要。

首要增加Ktor的依靠,代码如下所示。

val jvmMain by getting {
    dependencies {
        implementation(compose.desktop.currentOs)
        implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
        val ktorVersion = "2.1.2"
        implementation("io.ktor:ktor-client-core:$ktorVersion")
        implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
        implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
        implementation("io.ktor:ktor-client-android:$ktorVersion")
    }
}

增加一个Api接口

object Api {
    val dataApi = "https://wanandroid.com/wenda/list/1/json"
}

创立HttpUtil类,用于创立HttpClient对象和获取数据的办法,代码如下所示。

import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.Json
class HttpUtil {
    private val httpClient = HttpClient {
        install(ContentNegotiation) {
            json(Json {
                prettyPrint = true
                isLenient = true
                ignoreUnknownKeys = true
            })
        }
    }
    /**
     * 获取数据
     */
    suspend fun getData(): String {
        val rockets: DemoReqData =
            httpClient.get(Api.dataApi).body()
        return "${rockets.data} "
    }
}

DemoReqData是接口返回数据对应映射的实体类,这儿就不再给出了。

然后咱们编写UI,点击按钮开端网络恳求,代码如下所示。

Column() {
    val scope = rememberCoroutineScope()
    var demoReqData by remember { mutableStateOf(DemoReqData()) }
    Button(onClick = {
        scope.launch {
            try {
                demoReqData = HttpUtil().getData()
            } catch (e: Exception) {
            }
        }
    }) {
        Text(text = "恳求数据")
    }
    LazyColumn {
        repeat(demoReqData.data?.datas?.size ?: 0) {
            item {
                Message(demoReqData.data?.datas?.get(it))
            }
        }
    }
}

获取数据后,经过

Message办法

将数据展现出来,这儿只将作者与标题内容显示出来,代码如下所示。

@Composable
fun Message(data: DemoReqData.DataBean.DatasBean?) {
    Card(
        modifier = Modifier
            .background(Color.White)
            .padding(10.dp)
            .fillMaxWidth(), elevation = 10.dp
    ) {
        Column(modifier = Modifier.padding(10.dp)) {
            Text(
                text = "作者:${data?.author}"
            )
            Text(text = "${data?.title}")
        }
    }
}

运转程序,点击“恳求数据”,结果如下图所示。

Compose跨平台第一弹:体验Compose for Desktop

这样咱们就完成了一个简单的桌面端数据恳求与显示功用。

写在最终

当然,在Compose For Desktop中还有许多的组件,比如Tooltips、Context Menu等等,这儿无法一一介绍,需要咱们在运用的时候去实践,咱们将在后边的N弹中持续探索…

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。