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. 占位符文本逻辑

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

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

相关推荐
混迹中的咸鱼4 小时前
几何数据结构之四叉树与八叉树
android·数据结构
李歘歘5 小时前
Golang——常用库reflect和unsafe
android·服务器·golang
web182859970895 小时前
存储过程(SQL)
android·数据库·sql
LucianaiB8 小时前
C语言之装甲车库车辆动态监控辅助记录系统
android·c语言·开发语言·低代码
limingade8 小时前
从零搭建一套远程手机的桌面操控和文件传输的小工具
android·adb·智能手机·信息与通信·android runtime
2401_897915658 小时前
Android Jetpack 之 Paging3的一些踩坑记录
android·android jetpack
ghostwritten8 小时前
实战经验:使用 Python 的 PyPDF 进行 PDF 操作
android·python·pdf
2401_897915659 小时前
Android Http基础:图片下载并显示和WebView的应用
android·网络协议·http
李歘歘9 小时前
Golang——包的循环引用问题(import cycle not allowed)和匿名导入
android·数据库·golang