在 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 设计风格的效果。

相关推荐
Yang-Never7 分钟前
ADB -> pull指令推送电脑文件到手机上
android·adb·android studio
李新_9 分钟前
我们封装了哪些好用的Flutter Mixin
android·flutter
帅次23 分钟前
Flutter Expanded 与 Flexible 详解
android·flutter·ios·小程序·webview
流浪汉kylin26 分钟前
Android手机如何腾出存储空间
android
0wioiw01 小时前
Kotlin基础(①)
android·开发语言·kotlin
西瓜本瓜@1 小时前
在 Android 中实现通话录音
android·java·开发语言·学习·github·android-studio
浩浩测试一下2 小时前
信息收集之hack用的网络空间搜索引擎
android·网络·安全·web安全·搜索引擎·网络安全·安全架构
齐格Insight2 小时前
Capacitor 框架下解决One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be ...
android
芦半山2 小时前
后AOSP时代还能贡献代码吗?
android·源码
V少年3 小时前
深入浅出Java编译过程
android