You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin Jetpack Compose TextField无法接收输入问题求助

问题:TextField无法接收用户输入的编辑功能异常

已实现Firestore数据获取与UI展示功能,新增联系人号码编辑功能时,点击编辑按钮后TextField无法接收用户输入,电话、共享位置等其他功能运行正常。

相关代码

LazyColumn(
    modifier = Modifier
        .fillMaxWidth()
        .padding(horizontal = 16.dp)
) {
    item {
        if (firefighters != null) {
            for (firefighter in firefighters) {

                var contactNumber = firefighter.contactNumber
                val documentId = firefighter.documentId
                var editedContactNumber = remember { contactNumber }

                Spacer(modifier = Modifier.height(5.dp))
                Column {
                    Text(
                        text = "$documentId",
                        color = Color.Black,
                        style = LocalTextStyle.current,
                        modifier = Modifier
                            .paddingFromBaseline(
                                10.dp,
                                0.dp
                            ) // Adjust vertical spacing as needed
                    )


                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(50.dp)
                            .padding(5.dp),
                        horizontalArrangement = Arrangement.SpaceBetween
                    ) {
                        var isEditing by remember { mutableStateOf(false) }

                        Box(
                            modifier = Modifier
                                .size(width = 150.dp, height = 40.dp)
                                .border(2.dp, Color.Black)
                                .background(Color.White),
                            contentAlignment = Alignment.Center
                        ) {
                            if (isEditing) {
                                TextField(
                                    value = if (isEditing) editedContactNumber else "", // Show editedContactNumber if editing, otherwise show an empty string
                                    onValueChange = { newValue -> 
                                        // Check if the input is not empty and contains only numeric characters
                                        if (newValue.isNotEmpty() && newValue.all { char -> char.isDigit() }) {
                                            // Check if the length is less than or equal to 11 digits
                                            if (newValue.length <= 11) {
                                                editedContactNumber = newValue
                                                contactNumber = editedContactNumber
                                                contactNumber = newValue


                                            } else {
                                                Log.d("editedContactNumber", "editedContactNumber: Number Input is not Valid ")
                                            }
                                        } else {
                                            Log.d("EditInput", "Empty Field")
                                        }
                                        // You can provide feedback to the user or handle other cases as needed
                                    },
                                    textStyle = LocalTextStyle.current.copy(color = Color.Black, fontSize = 14.sp),
                                    keyboardOptions = KeyboardOptions.Default.copy(
                                        keyboardType = KeyboardType.Number
                                    ),
                                    modifier = Modifier.border(
                                        width = 2.dp,
                                        color = when {
                                            editedContactNumber.isEmpty() && !isEditing -> Color.Red // Display red border for empty input if not in editing mode
                                            editedContactNumber.length > 11 -> Color.Red // Display red border for more than 11 digits
                                            else -> Color.Black
                                        }
                                    )
                                )


                            } else {
                                Text(
                                    text = if (isEditing) {
                                        editedContactNumber
                                    } else {
                                        contactNumber
                                    },
                                    color = Color.Black,
                                    style = LocalTextStyle.current
                                )
                            }
                        }

                        Icon(
                            imageVector = if (isEditing) Icons.Default.Check else Icons.Default.Edit,
                            contentDescription = null,
                            tint = Color.Black,
                            modifier = Modifier
                                .size(24.dp)
                                .align(Alignment.Bottom)
                                .padding(bottom = 1.dp)
                                .clickable {
                                    if (!isEditing) {
                                        editedContactNumber = contactNumber
                                    }
                                    isEditing = !isEditing

                                    if (!isEditing) {
                                        if (editedContactNumber.length == 11) {
                                            // Update the contact number in Firestore
                                            if (finalMunicipalityForm != null) {

                                                val db = Firebase.firestore
                                                db.collection("Emergency Contacts")
                                                    .document("$finalMunicipalityForm")
                                                    .collection("Firefighters")
                                                    .document(documentId)
                                                    .update(
                                                        "contacts",
                                                        editedContactNumber
                                                    )
                                                    .addOnSuccessListener {
                                                        Log.d(
                                                            "EditNumber",
                                                            "Number updated successfully : $editedContactNumber"
                                                        )
                                                        isEditing = false
                                                        editedContactNumber = ""
                                                        context.showToast("Number Updated")
                                                    }
                                                    .addOnFailureListener { e -> 
                                                        Log.e(
                                                            "EditNumber",
                                                            "Error updating number",
                                                            e
                                                        )
                                                    }
                                            } else {
                                                context.showToast("Please enter a 11-digit number")
                                            }
                                        }
                                    }
                                }
                        )

                        Icon(
                            imageVector = Icons.Default.LocationOn,
                            contentDescription = null,
                            tint = Color.Black,
                            modifier = Modifier
                                .size(40.dp)
                                .clickable {
                                    userLocation?.let { location -> 
                                        // Call a function to handle sending SMS with location and phone number
                                        sendLocationSMS(
                                            context = context,
                                            location = location,
                                            phoneNumber = contactNumber
                                        )
                                    } ?: run {
                                        Log.w(
                                            "Clickable",
                                            "User location is null"
                                        )
                                    }
                                }
                        )

                        Spacer(modifier = Modifier.width(2.dp))

                        Icon(
                            imageVector = Icons.Default.Phone,
                            contentDescription = null,
                            tint = Color.Black,
                            modifier = Modifier
                                .size(40.dp)
                                .clickable {
                                    // Launch the dialer here
                                    val dialIntent = Intent(
                                        Intent.ACTION_DIAL,
                                        Uri.parse("tel:$contactNumber")
                                    )
                                    dialerLauncher.launch(dialIntent)
                                }
                        )
                    }

                    Spacer(
                        modifier = Modifier
                            .height(1.dp)
                            .fillMaxWidth()
                            .background(Color.Black)
                    )

                    Spacer(modifier = Modifier.height(5.dp))
                }
            }
        }
    }
}

问题原因与修复方案

核心问题

  1. editedContactNumber未使用mutableStateOf:当前定义的变量不是Jetpack Compose的可观察状态,修改后无法触发UI重组,导致TextField显示值不更新,看起来无法输入。
  2. 冗余赋值与逻辑混乱:onValueChange中重复对contactNumber赋值,保存后清空editedContactNumber会导致下次编辑初始值异常。
  3. TextField的value判断冗余:已处于isEditing分支,无需重复判断。

修复后的关键代码片段

// 替换原有的editedContactNumber定义
var editedContactNumber by remember { mutableStateOf(contactNumber) }

// 替换TextField部分
if (isEditing) {
    TextField(
        value = editedContactNumber,
        onValueChange = { newValue -> 
            if (newValue.all { it.isDigit() } && newValue.length <= 11) {
                editedContactNumber = newValue
            }
            // 空输入允许用户操作,保存时再做严格校验
        },
        textStyle = LocalTextStyle.current.copy(color = Color.Black, fontSize = 14.sp),
        keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number),
        modifier = Modifier.border(
            width = 2.dp,
            color = when {
                editedContactNumber.length > 11 -> Color.Red
                else -> Color.Black
            }
        )
    )
} else {
    Text(
        text = contactNumber,
        color = Color.Black,
        style = LocalTextStyle.current
    )
}

// 替换保存逻辑部分
Icon(
    imageVector = if (isEditing) Icons.Default.Check else Icons.Default.Edit,
    contentDescription = null,
    tint = Color.Black,
    modifier = Modifier
        .size(24.dp)
        .align(Alignment.Bottom)
        .padding(bottom = 1.dp)
        .clickable {
            if (!isEditing) {
                editedContactNumber = contactNumber
            } else {
                // 保存前校验
                if (editedContactNumber.length == 11) {
                    finalMunicipalityForm?.let { municipality ->
                        Firebase.firestore.collection("Emergency Contacts")
                            .document(municipality)
                            .collection("Firefighters")
                            .document(documentId)
                            .update("contacts", editedContactNumber)
                            .addOnSuccessListener {
                                Log.d("EditNumber", "Number updated successfully : $editedContactNumber")
                                // 更新本地变量,同步UI显示
                                contactNumber = editedContactNumber
                                context.showToast("Number Updated")
                            }
                            .addOnFailureListener { e -> 
                                Log.e("EditNumber", "Error updating number", e)
                                context.showToast("Update failed")
                            }
                    } ?: run {
                        context.showToast("Municipality not selected")
                    }
                } else {
                    context.showToast("Please enter a 11-digit number")
                    // 校验不通过时不退出编辑模式,让用户修正
                    return@clickable
                }
            }
            isEditing = !isEditing
        }
)

修复要点总结

  • 用mutableStateOf定义editedContactNumber,确保状态变化能触发UI重组。
  • 简化onValueChange逻辑,只在输入合法时更新状态,空输入允许用户操作,保存时再做严格校验。
  • 保存成功后同步更新本地contactNumber,确保UI显示最新值。
  • 校验不通过时不退出编辑模式,提升用户体验。

内容的提问来源于stack exchange,提问作者user19101467

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 21:35:00