在 Jetpack Compose 中实现 iOS 风格输入框

要在 Android Compose 中模仿 iOS 风格的输入框,我们需要关注几个关键特点:简洁的边框、圆角设计、特定的交互效果等。以下是完整的实现方案:

1. 基础 iOS 风格输入框

kotlin 复制代码
@Composable
fun IosStyleTextField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    label: String? = null,
    placeholder: String? = null
) {
    Column(modifier = modifier) {
        label?.let {
            Text(
                text = it,
                style = MaterialTheme.typography.bodyMedium,
                color = Color.Gray,
                modifier = Modifier.padding(bottom = 4.dp)
            )
        }
        
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .background(
                    color = Color.White,
                    shape = RoundedCornerShape(10.dp)
                )
                .border(
                    width = 1.dp,
                    color = Color(0xFFC7C7CC),
                    shape = RoundedCornerShape(10.dp)
                )
                .padding(horizontal = 16.dp, vertical = 12.dp)
        ) {
            BasicTextField(
                value = value,
                onValueChange = onValueChange,
                modifier = Modifier.fillMaxWidth(),
                textStyle = MaterialTheme.typography.bodyMedium.copy(
                    color = Color.Black
                ),
                singleLine = true,
                decorationBox = { innerTextField ->
                    if (value.isEmpty() && placeholder != null) {
                        Text(
                            text = placeholder,
                            style = MaterialTheme.typography.bodyMedium.copy(
                                color = Color(0xFFC7C7CC)
                            )
                        )
                    }
                    innerTextField()
                }
            )
        }
    }
}

// 使用示例
var text by remember { mutableStateOf("") }
IosStyleTextField(
    value = text,
    onValueChange = { text = it },
    label = "用户名",
    placeholder = "请输入用户名",
    modifier = Modifier.padding(16.dp)
)

2. 带清除按钮的 iOS 风格输入框

kotlin 复制代码
@Composable
fun IosStyleTextFieldWithClear(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    label: String? = null,
    placeholder: String? = null
) {
    Column(modifier = modifier) {
        label?.let {
            Text(
                text = it,
                style = MaterialTheme.typography.bodyMedium,
                color = Color.Gray,
                modifier = Modifier.padding(bottom = 4.dp)
            )
        }
        
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .background(
                    color = Color.White,
                    shape = RoundedCornerShape(10.dp)
                )
                .border(
                    width = 1.dp,
                    color = if (value.isNotEmpty()) Color(0xFF007AFF) else Color(0xFFC7C7CC),
                    shape = RoundedCornerShape(10.dp)
                )
                .padding(horizontal = 16.dp, vertical = 12.dp)
        ) {
            Row(
                verticalAlignment = Alignment.CenterVertically,
                modifier = Modifier.fillMaxWidth()
            ) {
                BasicTextField(
                    value = value,
                    onValueChange = onValueChange,
                    modifier = Modifier.weight(1f),
                    textStyle = MaterialTheme.typography.bodyMedium.copy(
                        color = Color.Black
                    ),
                    singleLine = true,
                    decorationBox = { innerTextField ->
                        if (value.isEmpty() && placeholder != null) {
                            Text(
                                text = placeholder,
                                style = MaterialTheme.typography.bodyMedium.copy(
                                    color = Color(0xFFC7C7CC))
                            )
                        }
                        innerTextField()
                    }
                )
                
                if (value.isNotEmpty()) {
                    IconButton(
                        onClick = { onValueChange("") },
                        modifier = Modifier.size(20.dp)
                    ) {
                        Icon(
                            imageVector = Icons.Default.Close,
                            contentDescription = "清除",
                            tint = Color(0xFFC7C7CC),
                            modifier = Modifier.size(16.dp)
                        )
                    }
                }
            }
        }
    }
}

3. 搜索框样式

kotlin 复制代码
@Composable
fun IosStyleSearchField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    placeholder: String = "搜索"
) {
    Box(
        modifier = modifier
            .fillMaxWidth()
            .height(36.dp)
            .background(
                color = Color(0xFFF2F2F7),
                shape = RoundedCornerShape(10.dp)
            )
            .padding(horizontal = 8.dp),
        contentAlignment = Alignment.CenterStart
    ) {
        Row(
            verticalAlignment = Alignment.CenterVertically,
            modifier = Modifier.fillMaxWidth()
        ) {
            Icon(
                imageVector = Icons.Default.Search,
                contentDescription = "搜索",
                tint = Color(0xFF8E8E93),
                modifier = Modifier.size(16.dp)
                    .padding(end = 4.dp)
            )
            
            BasicTextField(
                value = value,
                onValueChange = onValueChange,
                modifier = Modifier.weight(1f),
                textStyle = MaterialTheme.typography.bodyMedium.copy(
                    color = Color.Black,
                    fontSize = 14.sp
                ),
                singleLine = true,
                decorationBox = { innerTextField ->
                    if (value.isEmpty()) {
                        Text(
                            text = placeholder,
                            style = MaterialTheme.typography.bodyMedium.copy(
                                color = Color(0xFF8E8E93),
                                fontSize = 14.sp
                            )
                        )
                    }
                    innerTextField()
                }
            )
            
            if (value.isNotEmpty()) {
                IconButton(
                    onClick = { onValueChange("") },
                    modifier = Modifier.size(20.dp)
                ) {
                    Icon(
                        imageVector = Icons.Default.Close,
                        contentDescription = "清除",
                        tint = Color(0xFF8E8E93),
                        modifier = Modifier.size(16.dp)
                    )
                }
            }
        }
    }
}

4. 带分段的 iOS 风格表单

kotlin 复制代码
@Composable
fun IosStyleForm(
    items: List<Pair<String, @Composable () -> Unit>>,
    modifier: Modifier = Modifier
) {
    Column(
        modifier = modifier
            .background(Color.White)
            .clip(RoundedCornerShape(10.dp))
    ) {
        items.forEachIndexed { index, (title, content) ->
            Column {
                if (index > 0) {
                    Divider(
                        color = Color(0xFFC6C6C8),
                        thickness = 0.5.dp,
                        modifier = Modifier.padding(horizontal = 16.dp)
                    )
                }
                
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(horizontal = 16.dp, vertical = 12.dp),
                    verticalAlignment = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.SpaceBetween
                ) {
                    Text(
                        text = title,
                        style = MaterialTheme.typography.bodyMedium.copy(
                            color = Color.Black
                        ),
                        modifier = Modifier.weight(1f)
                    )
                    
                    Box(modifier = Modifier.weight(1f)) {
                        content()
                    }
                }
            }
        }
    }
}

// 使用示例
var username by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }

IosStyleForm(
    items = listOf(
        "账号" to {
            BasicTextField(
                value = username,
                onValueChange = { username = it },
                modifier = Modifier.fillMaxWidth(),
                textStyle = MaterialTheme.typography.bodyMedium.copy(
                    textAlign = TextAlign.End
                )
            )
        },
        "密码" to {
            BasicTextField(
                value = password,
                onValueChange = { password = it },
                modifier = Modifier.fillMaxWidth(),
                textStyle = MaterialTheme.typography.bodyMedium.copy(
                    textAlign = TextAlign.End
                ),
                visualTransformation = PasswordVisualTransformation()
            )
        }
    ),
    modifier = Modifier.padding(16.dp)
)

5. 动画效果增强

kotlin 复制代码
@Composable
fun AnimatedIosTextField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    label: String,
    placeholder: String
) {
    val animatedBorderColor by animateColorAsState(
        targetValue = if (value.isNotEmpty()) Color(0xFF007AFF) else Color(0xFFC7C7CC),
        label = "borderColorAnimation"
    )
    
    Column(modifier = modifier) {
        Text(
            text = label,
            style = MaterialTheme.typography.bodyMedium,
            color = Color.Gray,
            modifier = Modifier.padding(bottom = 4.dp)
        )
        
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .background(
                    color = Color.White,
                    shape = RoundedCornerShape(10.dp)
                )
                .border(
                    width = 1.dp,
                    color = animatedBorderColor,
                    shape = RoundedCornerShape(10.dp)
                )
                .padding(horizontal = 16.dp, vertical = 12.dp)
        ) {
            BasicTextField(
                value = value,
                onValueChange = onValueChange,
                modifier = Modifier.fillMaxWidth(),
                textStyle = MaterialTheme.typography.bodyMedium.copy(
                    color = Color.Black
                ),
                singleLine = true,
                decorationBox = { innerTextField ->
                    Box {
                        if (value.isEmpty()) {
                            Text(
                                text = placeholder,
                                style = MaterialTheme.typography.bodyMedium.copy(
                                    color = Color(0xFFC7C7CC))
                            )
                        }
                        innerTextField()
                    }
                }
            )
        }
    }
}

关键 iOS 风格特点实现

  1. 圆角设计

    kotlin 复制代码
    shape = RoundedCornerShape(10.dp)
  2. 边框颜色

    kotlin 复制代码
    borderColor = if (focused) Color(0xFF007AFF) else Color(0xFFC7C7CC)
  3. 占位符样式

    kotlin 复制代码
    color = Color(0xFFC7C7CC)
  4. 清除按钮

    kotlin 复制代码
    Icon(Icons.Default.Close, contentDescription = "清除")
  5. 分段列表样式

    kotlin 复制代码
    Divider(color = Color(0xFFC6C6C8), thickness = 0.5.dp)

这些组件可以根据你的具体需求进一步定制,调整颜色、尺寸和动画效果,以达到更接近 iOS 设计风格的效果。

相关推荐
数智工坊4 小时前
机器人运动控制:采样、优化与学习三大流派深度对比与实战
android·学习·机器人
故渊at6 小时前
第二板块:Android 四大组件标准化学理 | 第八篇:Service 后台执行实体与优先级
android·gitee·service·前台服务·后台服务
会Tk矩阵群控的小木6 小时前
安卓群控系统对于游戏工作室实战教程
android·运维·游戏·adb·开源软件·个人开发
qeen877 小时前
【C++】类与对象之类的默认成员函数(二)
android·c语言·开发语言·c++·笔记·学习
故渊at7 小时前
第二板块:Android 四大组件标准化学理 | 第九篇:BroadcastReceiver 事件分发与有序广播
android·gitee·broadcast·广播·动态注册·静态注册
JohnnyDeng948 小时前
【Android】Room 数据库高级用法与性能调优:从查询瓶颈到毫秒级响应
android·性能优化·kotlin·room
zeqinjie8 小时前
Flutter 折叠屏 iPad / 宽屏适配实践
android·前端·flutter
ab_dg_dp8 小时前
Android 17+ 提取 AIDL 生成 Java 文件的实用脚本
android·java·python
Arrom9 小时前
DLNA 渲染端排障实战:从 20s 卡顿到 stale subscriber 的两周追凶之旅
android·java