Android CustomTextField

在 Compose 中开发用户界面时,需要处理输入框和键盘的交互,例如在键盘弹出时调整布局位置,避免遮挡重要内容。本篇博客将通过一个完整的示例展示如何实现这一功能。

功能概述

本例实现了一个简单的输入框。当输入框获得焦点或输入文字时,以下行为发生:

  1. 键盘弹出。

  2. 输入框上方的占位符文本根据焦点状态和输入内容动态显示或隐藏。

  3. 整个布局根据键盘的弹出状态自动调整,避免内容被遮挡。

代码实现

复制代码
封装TextField代码:
Swift 复制代码
@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
            )
        }
    }
}

界面逻辑代码:

Kotlin 复制代码
@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)
        }
    }
}

核心实现

  1. 状态管理 使用 remembermutableStateOf 管理输入框文本内容 (textValue) 和焦点状态 (isTextFieldFocused)。

  2. 动画效果 借助 animateDpAsState 动态调整布局底部间距 bottomPadding,为界面变化提供平滑过渡。

  3. 输入框的焦点处理

    • 使用 onFocusChanged 检测输入框的焦点状态,更新 isTextFieldFocused

    • 在键盘输入完成时,通过 focusManager.clearFocus()keyboardController?.hide() 收起键盘。

  4. 占位符文本逻辑

    • 如果输入框内容为空且未聚焦,显示占位符。

    • 根据状态动态调整占位符的显示位置和样式。

相关推荐
liang_jy8 小时前
Android SparseArray
android·源码
liang_jy9 小时前
Activity 启动流程扩展篇(一)—— startActivityInner 任务决策全解析
android·源码
NPE~10 小时前
[App逆向]脱壳实战
android·教程·逆向·android逆向·逆向分析
木易 士心10 小时前
别再只会用 drawCircle 了!一文搞懂 Android Canvas 底层机制
android
AtOR CUES12 小时前
MySQL——表操作及查询
android·mysql·adb
怣疯knight13 小时前
安卓App无法增加自定义图片作为图标功能
android
jinanwuhuaguo14 小时前
OpenClaw联邦之心——从孤岛记忆到硅基集体潜意识的拓扑学革命(第二十三篇)
android·人工智能·kotlin·拓扑学·openclaw
Gary Studio16 小时前
安卓HAL C++基础-命名域
android
诸神黄昏EX16 小时前
Android Google XTS
android
eSsO KERF17 小时前
MySQL Workbench菜单汉化为中文
android·数据库·mysql