写了个简单的界面,包含功能:
1,列表中动态增加行和删除行
2,根据列表中的数据生成 json。
包含的文件或类:
1,Main.kt, 程序入口,使用 Window 即是 desktop 端。
2,View.kt, 画界面,只展示数据,没有业务逻辑。
3,ViewModel.kt,与View“绑定”,给View提供数据,及响应View接收到的用户操作。
4,Repository.kt,模拟读取数据库。
5,ViewStatus.kt,可以理解为元数据,状态。
效果:
程序很简单,不多说,直接贴代码
1,Main.kt
/**
* 入口
*/
fun main() = application {
Window(state = WindowState(), onCloseRequest = ::exitApplication, title = "记录转 JSON") {
App()
}
}
2,View.kt
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
/**
* 画界面
*/
private val viewModel: ViewModel = ViewModel()
@Composable
@Preview
fun App() {
val dataList: MutableList = remember { viewModel.viewState.paramList }
val options: MutableList> = mutableListOf()
options.add(Pair("是", true))
options.add(Pair("否", false))
//byLazyColumn(dataList, options)
byScrollBar(dataList, options)
}
/**
* 使用 LazyColumn,不会显示滚动条
*/
@Composable
fun byLazyColumn(list: MutableList, drops: MutableList>) {
MaterialTheme {
//dataList.add(Param("参数项描述", "参数值", 0))
//dataList.add(Param("", "", 0))
//val stateVertical = rememberScrollState(0)
LazyColumn(
verticalArrangement = Arrangement.spacedBy(5.dp) // 行间距
) {
item {
renderHead()
}
itemsIndexed(list) { idx, item ->
renderItem(item, list, idx, drops)
}
item {
renderTail()
}
}
}
}
/**
* 有滚动条
*/
@Composable
fun byScrollBar(list: MutableList, drops: MutableList>) {
Column {
renderHead()
Row {
Box(//必须要包在 Box 里面,滚动条才会显示出来
modifier = Modifier.height(400.dp).fillMaxWidth()
//.background(color = Color(180, 180, 180))
.padding(10.dp)
) {
val stateVertical = rememberScrollState(0)
Column(
modifier = Modifier.height(400.dp)
.verticalScroll(stateVertical).fillMaxWidth()
.padding(end = 12.dp, bottom = 12.dp)
) {
list.forEachIndexed { idx, item ->
renderItem(item, list, idx, drops)
}
}
VerticalScrollbar(
modifier = Modifier.align(Alignment.CenterEnd),
adapter = rememberScrollbarAdapter(stateVertical)
)
}
}
renderTail()
}
}
/**
* 画一行
*/
@Composable
fun renderItem(item: Param, list: MutableList, index: Int, drops: MutableList>) {
val content = remember { mutableStateOf(item.content) }
val isdtc = remember { mutableStateOf(item.isdtc) }
val value = remember { mutableStateOf(TextFieldValue(if (item.value == null) "" else item.value.toString())) }
Row {
OutlinedTextField(
value = content.value,
modifier = Modifier.padding(horizontal = 20.dp).width(150.dp),
onValueChange = {
item.content = it
content.value = it
})
OutlinedTextField(value = value.value,
modifier = Modifier.padding(horizontal = 20.dp).width(150.dp),
onValueChange = {
try {
item.value = it.text.toInt()
value.value = it
} catch (e: Exception) {
item.value = null
value.value = TextFieldValue("")
}
})
drops.forEach { option ->
Row(
Modifier.width(95.dp),
verticalAlignment = Alignment.CenterVertically
) {
RadioButton(
// 通过观察对象和index相同判断是否被选中
selected = (isdtc.value == option.second),
// 点击事件
onClick = {
isdtc.value = option.second
item.isdtc = option.second
}
)
Text(
text = option.first
)
}
}
// DropdownMenu(expanded = true, modifier = Modifier.padding(horizontal = 20.dp).width(150.dp), onDismissRequest = {}) {
// drops.forEach {
// DropdownMenuItem(onClick = {
// item.value = it.second
// }) {
// Text(text = it.first)
// }
// }
// }
if (index == list.size - 1) {
Button(modifier = Modifier.padding(horizontal = 20.dp), onClick = {
//list.removeAt(index)
val removeItemAction = ViewAction.RemoveItemAction()
removeItemAction.target = item
viewModel.dispatch(removeItemAction)
}) {
Text("删除")
}
}
}
}
/**
* 表头
*/
@Composable
fun renderHead() {
Row(horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically) {
Text(
text = "参数项描述",
modifier = Modifier.padding(horizontal = 20.dp).width(150.dp),
textAlign = TextAlign.Center
)
Text(
text = "参数值",
modifier = Modifier.padding(horizontal = 20.dp).width(150.dp),
textAlign = TextAlign.Center
)
Text(
text = "是否故障",
modifier = Modifier.padding(horizontal = 20.dp).width(150.dp),
textAlign = TextAlign.Center
)
Button(modifier = Modifier.padding(horizontal = 20.dp), onClick = {
//list.add(Param("", null, false))
viewModel.dispatch(ViewAction.AddItemAction)
}) {
Text("增加")
}
}
}
/**
* 底部的按钮“生成json”和大文本框
*/
@Composable
fun renderTail() {
Row(horizontalArrangement = Arrangement.Center) {
val state = remember {viewModel.viewState.result}
Button(modifier = Modifier.padding(horizontal = 20.dp), onClick = {
viewModel.dispatch(ViewAction.GenerateJsonAction)
}) {
Text("生成 JSON")
}
OutlinedTextField(
value = state.value,
onValueChange = { text -> state.value = text },
modifier = Modifier.width(500.dp)
)
}
}
3,ViewModel.kt
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.toMutableStateList
class ViewModel {
private val repository = Repository()
val viewState: ViewState = ViewState(repository.query().toMutableStateList(), mutableStateOf(""))
private fun generateJson() {
val json = StringBuilder("[")
viewState.paramList.forEach {
if (it.content.isNotEmpty()) {
json.append("$it,")
}
}
if (json.endsWith(",")) {
json.delete(json.length - 1, json.length)
}
json.append("]")
viewState.result.value = json.toString()
}
private fun addItem() {
viewState.paramList.add(Param("", null, false))
}
private fun removeItem(item: Param?) {
if (item != null) {
viewState.paramList.remove(item)
}
}
fun dispatch(action: ViewAction) {
when(action) {
ViewAction.GenerateJsonAction -> generateJson()
ViewAction.AddItemAction -> addItem()
else ->
if (action is ViewAction.RemoveItemAction) {
removeItem(action.target)
}
}
}
}
4,Repository.kt
/**
* 管理数据,或者处理业务逻辑
*/
class Repository {
fun query(): MutableList{
val list: MutableList = mutableListOf()
list.add(Param("", null, false))
return list
}
}
5,ViewStatus.kt
import androidx.compose.runtime.MutableState
/**
* 界面上的数据:一个列表,及根据列表生成的 json
*/
data class ViewState(val paramList: MutableList, var result: MutableState)
/**
* 界面上的操作定义
*/
sealed class ViewAction {
/** 增加一行 */
object AddItemAction: ViewAction()
/** 生成 json */
object GenerateJsonAction: ViewAction()
/** 删除一行 */
class RemoveItemAction: ViewAction() {
var target: Param? = null
}
}
/**
* 列表中显示的数据类型
*/
data class Param(var content: String, var value: Int?, var isdtc: Boolean) {
override fun toString(): String {
return if (value != null) "{\"content\":\"$content\", \"value\":$value, \"isdtc\":\"$isdtc\"}"
else "{\"content\":\"$content\", \"isdtc\":\"$isdtc\"}"
}
}