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

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

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

相关推荐
恋猫de小郭14 小时前
Dart 3.10 发布,快来看有什么更新吧
android·前端·flutter
恋猫de小郭16 小时前
Flutter 3.38 发布,快来看看有什么更新吧
android·前端·flutter
百锦再21 小时前
第11章 泛型、trait与生命周期
android·网络·人工智能·python·golang·rust·go
会跑的兔子1 天前
Android 16 Kotlin协程 第二部分
android·windows·kotlin
键来大师1 天前
Android15 RK3588 修改默认不锁屏不休眠
android·java·framework·rk3588
江上清风山间明月1 天前
Android 系统超级实用的分析调试命令
android·内存·调试·dumpsys
百锦再1 天前
第12章 测试编写
android·java·开发语言·python·rust·go·erlang
用户69371750013841 天前
Kotlin 协程基础入门系列:从概念到实战
android·后端·kotlin
SHEN_ZIYUAN1 天前
Android 主线程性能优化实战:从 90% 降至 13%
android·cpu优化
曹绍华1 天前
android 线程loop
android·java·开发语言