我可以通过 Compose Multiplatform 中的单独按钮更改组件的值吗?
我正在尝试制作一个桌面应用程序,允许您搜索存储在单独目录中的 Kotlin 类中的许多预定义位置。为了实现这一点,我使用了 反射 和 compose-jb 库。
我遇到的问题是,当我在输入要搜索的标签后按下搜索按钮时,我无法弄清楚如何更新框列(位于另一个框组件中)以进行更改。
下面是我的代码(针对 Main.kt 文件),它描述了整个桌面应用程序。
val reflections = Reflections("io.github.mobomega.project.attractions")
var display = mutableSetOf<Attraction>()
fun main() = application {
val stateVertical = rememberScrollState(0)
val stateHorizontal = rememberScrollState(0)
var state = Box(
modifier = Modifier
.fillMaxSize()
.verticalScroll(stateVertical)
.padding(end = 12.dp, bottom = 12.dp)
.horizontalScroll(stateHorizontal)
)
Window(
onCloseRequest = ::exitApplication,
title = "Search",
state = rememberWindowState(width = 2256.dp, height = 1504.dp)
) {
val count = remember { mutableStateOf(1) }
MaterialTheme {
Column {
val text = remember { mutableStateOf("") }
OutlinedTextField(
value = text.value,
singleLine = true,
onValueChange = { text.value = it },
modifier = Modifier.align(Alignment.CenterHorizontally)
)
Row (modifier = Modifier.size(2256.dp, 50.dp), horizontalArrangement = Arrangement.Center) {
Button(modifier = Modifier.align(Alignment.Top),
onClick = {
val tags = text.value.split(", ", ",")
for (tag in tags) {
search(tag.lowercase())
println("$display have tag $tag")
}
// Setting the new value of the Box
state = create(stateVertical, stateHorizontal)
// Creates error:
// "@Composable invocations can only happen from the context of a @Composable function"
}) {
Text("Search")
}
Button (modifier = Modifier.align(Alignment.Top),
onClick = {
display.clear()
}) {
Text("Reset")
}
}
Row (horizontalArrangement = Arrangement.Center) {
Box(
modifier = Modifier.fillMaxSize()
.background(color = Color(red = 0xFF, green = 0xFF, blue = 0xFF))
.padding(10.dp)
) {
state // Creating the state Box component in the Row
VerticalScrollbar(
modifier = Modifier.align(Alignment.CenterEnd)
.fillMaxHeight(),
adapter = rememberScrollbarAdapter(stateVertical)
)
HorizontalScrollbar(
modifier = Modifier.align(Alignment.BottomStart)
.fillMaxWidth()
.padding(end = 12.dp),
adapter = rememberScrollbarAdapter(stateHorizontal)
)
}
}
}
}
}
}
@Composable
fun textBox(text: String = "Item") {
Box(
modifier = Modifier.height(32.dp)
.width(400.dp)
.background(color = Color(200, 0, 0, 20))
.padding(start = 10.dp),
contentAlignment = Alignment.CenterStart
) {
Text(text = text)
}
}
@Composable
fun create(stateVertical: ScrollState, stateHorizontal: ScrollState) = Box(
modifier = Modifier
.fillMaxSize()
.verticalScroll(stateVertical)
.padding(end = 12.dp, bottom = 12.dp)
.horizontalScroll(stateHorizontal)
) {
Column {
var x = 0
for (attr in display) {
x++
textBox(attr.name)
if (x < display.size) {
Spacer(modifier = Modifier.height(5.dp).align(Alignment.CenterHorizontally))
}
}
}
}
fun search(text: String) {
for (attr in reflections.getSubTypesOf(Attraction::class.java)) {
val temp = attr.getConstructor().newInstance()
println("${temp.name} has tags ${temp.tags}")
if (temp.matches(text) && (temp !in display)) {
display += temp
}
}
}
我尝试更新包含与任何搜索条件匹配的所有项目的 Box 的值,但遇到了许多问题,例如在“onClick”函数中我设置了“状态”变量(存储所有匹配项)不是可组合函数,因此我无法更改该值。
我如何完成从另一个组件(例如按钮)更改组件(例如框)的值?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在 Compose 中,您无法像使用
state
变量那样创建视图。调用的结果只是Unit
,当您稍后调用它时,您应该会看到一条警告“表达式未使用”。创建变量时,视图将添加到树层次结构中。要解决您的问题,您需要将
display
声明为可变状态 - 这是专门为 Compose 制作的新事物,它允许在状态更改时触发重组:然后在您的
搜索中进行更新
:请注意,您不能在可变状态中使用可变集,因为可变状态将无法跟踪该集的更改。
要了解有关 Compose 中状态的更多信息,我建议您查看此 YouTube 视频,其中解释了基本原理,并了解 Compose 心理模型,以便更好地理解如何使用它。
In Compose you can't create a view like you're doing with
state
variable. Result of your call is justUnit
, and when you later call it you should see a warning "The expression is unused". The view is added at the tree hierarchy at the moment your variable is created.To solve your problem you need to declare
display
as a mutable state - it's a new thing made especially for Compose, which allows triggering recomposition when this state changes:And then update like this in your
search
:Note that you can't use mutable set inside your mutable state, as mutable state won't be able to track changes of this set.
To learn more about state in Compose I suggest you checking this youtube video which explains the basic principles, and Compose mental model for better understanding of how to work with it.