Android CustomTextField
在 Compose 中开发用户界面时,需要处理输入框和键盘的交互,例如在键盘弹出时调整布局位置,避免遮挡重要内容。本篇博客将通过一个完整的示例展示如何实现这一功能。
功能概述
本例实现了一个简单的输入框。当输入框获得焦点或输入文字时,以下行为发生:
-
键盘弹出。
-
输入框上方的占位符文本根据焦点状态和输入内容动态显示或隐藏。
-
整个布局根据键盘的弹出状态自动调整,避免内容被遮挡。
代码实现
封装TextField代码:
@Composable
fun CustomTextField(placeholderText: String, imageVector: Any) {
// 定义状态变量管理输入框的文本和焦点状态
var textValue by remember { mutableStateOf("") }
var isTextFieldFocused by remember { mutableStateOf(false) }
// 获取焦点管理器和键盘控制器
val focusManager = LocalFocusManager.current
val keyboardController = LocalSoftwareKeyboardController.current
// 动态计算底部间距,键盘弹出时调整布局
val bottomPadding by animateDpAsState(
targetValue = if (isTextFieldFocused || textValue.isNotEmpty()) 40.dp else 16.dp
)
// 使用 Box 包裹输入框和占位符文本
Box {
Column(
modifier = Modifier
.fillMaxWidth()
.height(70.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Bottom
) {
// 输入框组件
Row(
modifier = Modifier
.border(1.dp, Color.Black, RoundedCornerShape(16.dp))
.clip(RoundedCornerShape(16.dp))
.padding(0.dp) // 确保内边距为 0,避免额外的间距
) {
// 在 TextField 前添加图标,根据传入的 imageVector 参数显示不同图标
Icon(
imageVector = imageVector as androidx.compose.ui.graphics.vector.ImageVector,
contentDescription = "Icon",
modifier = Modifier
.size(35.dp)
.padding(
start = 10.dp,
top = 15.dp,
end = 0.dp,
bottom = 0.dp
)
)
TextField(
value = textValue,
onValueChange = { newText ->
textValue = newText
},
modifier = Modifier
.width(300.dp)
.height(50.dp)
.onFocusChanged { focusState ->
isTextFieldFocused = focusState.isFocused
},
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = {
isTextFieldFocused = false
focusManager.clearFocus()
}
)
)
}
}
Column(
modifier = Modifier
.fillMaxWidth()
.height(70.dp),
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Bottom
) {
// 占位符文本
Text(
text = placeholderText,
modifier = Modifier
.padding(
start = 40.dp,
top = 0.dp,
end = 0.dp,
bottom = bottomPadding
)
.background(Color(235, 226, 241)),
color = Color.Gray
)
}
}
}
界面逻辑代码:
@Composable
fun BoxAlignmentExample() {
// 设置 Surface 作为背景容器,填充整个屏幕
Surface(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
color = Color(235, 226, 241)
) {
// 使用 Column 布局排列内容
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top
) {
// name
CustomTextField(placeholderText = " 请输入账号 ", imageVector = Icons.Default.Person)
// password
CustomTextField(placeholderText = " 请输入密码 ", imageVector = Icons.Default.Lock)
}
}
}
核心实现
-
状态管理 使用
remember
和mutableStateOf
管理输入框文本内容 (textValue
) 和焦点状态 (isTextFieldFocused
)。 -
动画效果 借助
animateDpAsState
动态调整布局底部间距bottomPadding
,为界面变化提供平滑过渡。 -
输入框的焦点处理
-
使用
onFocusChanged
检测输入框的焦点状态,更新isTextFieldFocused
。 -
在键盘输入完成时,通过
focusManager.clearFocus()
和keyboardController?.hide()
收起键盘。
-
-
占位符文本逻辑
-
如果输入框内容为空且未聚焦,显示占位符。
-
根据状态动态调整占位符的显示位置和样式。
-