android 单击按钮时TextField值更改

7gcisfzg  于 2023-11-15  发布在  Android
关注(0)|答案(1)|浏览(97)

我是一个初学程序员,创建一个足球应用程序来模拟锦标赛的小组赛阶段。然而,我遇到了一个我无法处理的问题。我创建了一个屏幕,顶部有按钮来更改组,但是当我更改组时,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)
            }
        }
    }
}

个字符

yyhrrdl8

yyhrrdl81#

(我希望我回答对了你的问题)。
我猜你期望的行为是,当MatchResultInputmatchResult的值改变时,你的文本字段将更新为新值。然而,事实并非如此。State对象在重组过程中保持不变,不管是什么触发了它,包括可组合对象的参数的改变。
有两种方法可以更改文本输入
1.正确的做法是不要使用这两个state对象。相反,只需将updateScoreAupdateScoreB两个函数传递给MatchResultInput,然后将state hoist 传递给父组件。现在,您可以直接使用matchResult的值作为文本输入的参数,并且每当父组件更新它时,您的文本输入应该也会更新asa
1.更快的解决方案是,只需向matchResult.scoreA添加一个带有依赖关系的LaunchedEffect,以便在scoreA和scoreB发生变化时更新状态

相关问题