我是一个初学程序员,创建一个足球应用程序来模拟锦标赛的小组赛阶段。然而,我遇到了一个我无法处理的问题。我创建了一个屏幕,顶部有按钮来更改组,但是当我更改组时,ScoreInput字段(这是一个OutlinedTextField)具有来自前一组的值,我希望这些值是初始值,即0:0.我意识到这仍然是同一个TextField,我只是改变了它旁边显示的球队,但我不知道如何解决这个问题(创建6个看起来相同的独立屏幕对我来说也不是一个好主意).我也意识到应用程序不应该在UI层包含这么多逻辑,尽管我想在稍后阶段进行优化。我希望有人能帮助我,并提前非常感谢您的帮助。
此外,它需要保留的选项,用户不能编辑批准的结果在同一组,只有在改变组的进一步阶段的应用程序
我的屏幕代码:
@Composable
fun GroupStageScreen(viewModel: EuroViewModel) {
val groups = listOf("A", "B", "C", "D", "E", "F")
val (matchResult, setMatchResult) = remember { mutableStateOf(MutableList(6) { EuroMatchResult(0, 0) }) }
val groupData by viewModel.groupData.collectAsState(emptyList())
val (selectedGroup, setSelectedGroup) = remember { mutableStateOf(groups[0]) }
Surface(
modifier = Modifier.fillMaxSize(),
color = background_color
) {
Column(
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.CenterHorizontally
) {
// Buttons for changing groups
Row(
modifier = Modifier
.padding(5.dp)
.padding(top = 10.dp),
verticalAlignment = Alignment.Top,
horizontalArrangement = Arrangement.Center
) {
groups.forEach { groupInfo ->
Button(
onClick = {
setSelectedGroup(groupInfo)
},
modifier = Modifier.padding(2.dp),
shape = RoundedCornerShape(15.dp),
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Gray,
contentColor = Color.White
)
) {
Text(text = groupInfo)
}
}
}
val selectedGroupData = groupData.find { it.group == selectedGroup }
selectedGroupData?.let {groupInfo ->
// Group Table
Text(
text = "Group ${groupInfo.group}",
color = Color.White,
style = MaterialTheme.typography.h4,
textAlign = TextAlign.Center
)
Surface(
modifier = Modifier
.padding(7.dp)
.padding(top = 10.dp),
color = Color.Gray,
shape = RoundedCornerShape(10.dp),
border = BorderStroke(2.dp, Color.Gray),
elevation = 10.dp
) {
TeamTable(groupInfo.teams)
}
// Fields to fill the results
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Enter the match results: ",
color = Color.White,
style = MaterialTheme.typography.h6
)
Spacer(modifier = Modifier.height(8.dp))
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.padding(bottom = 30.dp)
) {
for (i in 0 until groupInfo.teams.size - 1) {
for (j in i + 1 until groupInfo.teams.size) {
val teamA = groupInfo.teams[i]
val teamB = groupInfo.teams[j]
val result = matchResult[i * 2 + j - (i * 1)]
MatchResultInput(
teamA = teamA.shortName,
teamB = teamB.shortName,
matchResult = result,
onResultChanged = { newResult ->
val updatedMatchResult = matchResult.toMutableList()
updatedMatchResult[i * 2 + j - (i + 1)] = newResult
setMatchResult(updatedMatchResult)
if (newResult.scoreA > newResult.scoreB) {
teamA.matchesPlayed++
teamA.matchesWon++
teamA.points += 3
teamB.matchesPlayed++
teamB.matchesLost++
} else if (newResult.scoreA < newResult.scoreB) {
teamA.matchesPlayed++
teamA.matchesLost++
teamB.matchesPlayed++
teamB.matchesWon++
teamB.points += 3
} else {
// It's a draw
teamA.matchesPlayed++
teamA.matchesDrawn++
teamA.points++
teamB.matchesPlayed++
teamB.matchesDrawn++
teamB.points++
}
})
}
}
}
}
}
}
}
@Composable
fun MatchResultInput(
teamA: String,
teamB: String,
matchResult: EuroMatchResult,
onResultChanged: (EuroMatchResult) -> Unit) {
val scoreA = remember { mutableStateOf(matchResult.scoreA.toString()) }
val scoreB = remember { mutableStateOf(matchResult.scoreB.toString()) }
val showPredictions = remember { mutableStateOf(false) }
val buttonEnabled = remember { mutableStateOf(true) }
Surface(
modifier = Modifier
.padding(start = 7.dp, end = 7.dp, top = 20.dp),
color = Color.Gray,
shape = RoundedCornerShape(topStart = 40.dp, topEnd = 40.dp), //30
border = BorderStroke(3.dp, Color.White),
elevation = 10.dp
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(4.dp)
.padding(start = 15.dp, end = 15.dp, bottom = 5.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(end = 8.dp)
) {
Image(
painterResource(id = R.drawable.flag_poland),
contentDescription = null,
modifier = Modifier.size(70.dp) //70
)
Text(
text = teamA,
fontSize = 19.sp
)
}
ScoreInput(
scoreState = scoreA,
onAction = KeyboardActions { FocusRequester.Default.requestFocus() },
enabled = true,
onScoreChanged = {newScore ->
scoreA.value = newScore
}
)
Column(
verticalArrangement = Arrangement.SpaceBetween,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = ":",
modifier = Modifier.padding(top = 40.dp,bottom = 12.dp),
textAlign = TextAlign.Center)
Button(
onClick = {
onResultChanged(EuroMatchResult(scoreA.value.toIntOrNull() ?: 0, scoreB.value.toIntOrNull() ?: 0))
showPredictions.value = true
buttonEnabled.value = false
},
modifier = Modifier.size(34.dp),
shape = CircleShape,
colors = ButtonDefaults.buttonColors(backgroundColor = green_check, contentColor = Color.White, disabledBackgroundColor = little_green_check),
enabled = buttonEnabled.value) {
Text(text = "✓", fontSize = 12.sp, textAlign = TextAlign.Center, fontWeight = FontWeight.Bold)
}
}
ScoreInput(scoreState = scoreB,
onScoreChanged = { newScore ->
scoreB.value = newScore
})
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(start = 8.dp)
) {
Image(
painterResource(id = R.drawable.flag_germany),
contentDescription = null,
modifier = Modifier.size(70.dp)
)
Text(
text = teamB,
fontSize = 19.sp
)
}
}
}
Surface(modifier = Modifier.padding(start = 7.dp, end = 7.dp),
color = Color.White,
shape = RoundedCornerShape(bottomStart = 40.dp, bottomEnd = 40.dp), //30
elevation = 10.dp) {
Row(modifier = Modifier
.fillMaxWidth()
.padding(top = 5.dp, bottom = 5.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center) {
if (!showPredictions.value){
Text(
text = "Confirm the result to see other players predictions",
modifier = Modifier.padding(7.dp),
textAlign = TextAlign.Center)
} else {
Text(text = "33%", modifier = Modifier.weight(1f), textAlign = TextAlign.Center, fontSize = 20.sp, fontWeight = FontWeight.Bold)
Text(text = "34%", modifier = Modifier.weight(1f), textAlign = TextAlign.Center, fontSize = 20.sp, fontWeight = FontWeight.Bold)
Text(text = "33%", modifier = Modifier.weight(1f), textAlign = TextAlign.Center, fontSize = 20.sp, fontWeight = FontWeight.Bold)
}
}
}
}
@Composable
fun TeamTable(teams: List<Team>) {
val sortedTeams = teams.sortedByDescending { it.points }
Column(modifier = Modifier.padding(3.dp)) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
val headerTitles = listOf("M", "W", "D", "L", "Pts")
Text(
"Country",
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center,
modifier = Modifier.width(150.dp)
)
headerTitles.forEach { titles ->
Text(
text = titles,
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center,
modifier = Modifier.width(50.dp)
)
}
}
sortedTeams.forEachIndexed { index, team ->
Surface(color = Color.White) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Image(
painterResource(id = R.drawable.flag_poland),
contentDescription = null,
modifier = Modifier.size(30.dp)
)
Text(
team.name,
textAlign = TextAlign.Start,
modifier = Modifier
.width(120.dp)
.padding(start = 10.dp)
)
listOf(
team.matchesPlayed,
team.matchesWon,
team.matchesDrawn,
team.matchesLost,
team.points).forEach { value ->
Text(
text = value.toString(),
textAlign = TextAlign.Center,
modifier = Modifier.width(50.dp)
)
}
}
Divider(thickness = 2.dp)
}
}
}
}
个字符
1条答案
按热度按时间yyhrrdl81#
(我希望我回答对了你的问题)。
我猜你期望的行为是,当
MatchResultInput
中matchResult
的值改变时,你的文本字段将更新为新值。然而,事实并非如此。State
对象在重组过程中保持不变,不管是什么触发了它,包括可组合对象的参数的改变。有两种方法可以更改文本输入
1.正确的做法是不要使用这两个state对象。相反,只需将
updateScoreA
和updateScoreB
两个函数传递给MatchResultInput
,然后将state hoist 传递给父组件。现在,您可以直接使用matchResult
的值作为文本输入的参数,并且每当父组件更新它时,您的文本输入应该也会更新asa1.更快的解决方案是,只需向
matchResult.scoreA
添加一个带有依赖关系的LaunchedEffect,以便在scoreA和scoreB发生变化时更新状态