Jetpack Compose中BasicTextField聚焦时标签定位异常问题求助
Jetpack Compose BasicTextField标签聚焦异常问题修复
问题描述
使用Jetpack Compose的BasicTextField和BasicSecureTextField搭配TextFieldDefaults.DecorationBox时,点击文本框获取焦点后,标签无法正常过渡到顶部位置,只有输入文本后才会恢复正常的标签状态。
问题原因
核心问题在于每次组件重组时都会创建新的MutableInteractionSource实例:
你在decorator lambda内部使用remember { MutableInteractionSource() },而decorator会在BasicTextField每次重组时执行,导致新的交互源实例被创建,DecorationBox无法持续跟踪焦点状态,进而触发错误的标签动画逻辑。
修复方案
- 将
MutableInteractionSource提升到组件函数级别,用remember创建,确保整个组件生命周期内实例唯一,让DecorationBox能正确跟踪焦点变化 - 修正
BasicSecureTextField的visualTransformation,使用PasswordVisualTransformation()实现密码隐藏效果(原代码用VisualTransformation.None会导致密码明文显示)
修改后的代码
MainActivity.kt
package com.example.baisctextfieldexample import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.BasicSecureTextField import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.foundation.text.input.rememberTextFieldState import androidx.compose.foundation.text.input.PasswordVisualTransformation import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Text import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.unit.dp import com.example.baisctextfieldexample.ui.theme.BaiscTextFieldExampleTheme class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { BaiscTextFieldExampleTheme { val stateOne = rememberTextFieldState() val stateTwo = rememberTextFieldState() BasicTextFieldExamples(stateOne, stateTwo) } } } @OptIn(ExperimentalMaterial3Api::class) @Composable fun BasicTextFieldExamples(stateOne: TextFieldState, stateTwo: TextFieldState) { // 提升交互源到函数级别,确保实例唯一 val usernameInteractionSource = remember { MutableInteractionSource() } val passwordInteractionSource = remember { MutableInteractionSource() } Column( Modifier .fillMaxSize() .padding(50.dp) ) { BasicTextField( state = stateOne, modifier = Modifier .fillMaxWidth() .height(56.dp), keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Email, imeAction = ImeAction.Next ), decorator = { TextFieldDefaults.DecorationBox( value = stateOne.text.toString(), innerTextField = it, enabled = true, singleLine = true, visualTransformation = VisualTransformation.None, label = { Text("Username") }, placeholder = { Text("Username Placeholder") }, // 使用外部创建的交互源 interactionSource = usernameInteractionSource ) } ) BasicSecureTextField( state = stateTwo, modifier = Modifier .fillMaxWidth() .height(56.dp), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), decorator = { TextFieldDefaults.DecorationBox( value = stateTwo.text.toString(), innerTextField = it, enabled = true, singleLine = true, // 修正密码可视化转换 visualTransformation = PasswordVisualTransformation(), label = { Text("Password") }, placeholder = { Text("Password Placeholder") }, // 使用外部创建的交互源 interactionSource = passwordInteractionSource ) } ) } } }
额外说明
当前使用的Material3版本(1.4.0-alpha06)本身不存在该问题,完全是代码写法导致的状态跟踪错误。修复后,点击文本框获取焦点时,标签会正常过渡到顶部,无需输入文本即可触发正确的动画。
内容的提问来源于stack exchange,提问作者Compose Learner
相关产品推荐
相关产品推荐

