Jetpack Compose 输入框完整解决方案

Jetpack Compose 输入框完整解决方案

以下是一个整合了各种最佳实践的完整输入框解决方案,包含基础输入、密码输入、搜索框、带计数功能和多行输入等多种场景:

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.*
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.delay

@Composable
fun ComprehensiveInputFields() {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp)
    ) {
        // 1. 基础输入框
        BasicInputField()
        
        Spacer(modifier = Modifier.height(16.dp))
        
        // 2. 密码输入框
        PasswordInputField()
        
        Spacer(modifier = Modifier.height(16.dp))
        
        // 3. 搜索输入框
        SearchInputField()
        
        Spacer(modifier = Modifier.height(16.dp))
        
        // 4. 带字符计数的输入框
        CountingInputField()
        
        Spacer(modifier = Modifier.height(16.dp))
        
        // 5. 多行文本输入框
        MultiLineInputField()
        
        Spacer(modifier = Modifier.height(16.dp))
        
        // 6. 防抖动输入框
        DebouncedInputField()
    }
}

@Composable
private fun BasicInputField() {
    var text by remember { mutableStateOf("") }
    
    OutlinedTextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("基础输入") },
        placeholder = { Text("请输入内容...") },
        modifier = Modifier.fillMaxWidth(),
        colors = TextFieldDefaults.outlinedTextFieldColors(
            focusedBorderColor = MaterialTheme.colors.primary,
            unfocusedBorderColor = MaterialTheme.colors.onSurface.copy(alpha = 0.2f)
        )
    )
}

@Composable
private fun PasswordInputField() {
    var password by rememberSaveable { mutableStateOf("") }
    var passwordVisible by rememberSaveable { mutableStateOf(false) }
    
    OutlinedTextField(
        value = password,
        onValueChange = { password = it },
        label = { Text("密码输入") },
        placeholder = { Text("请输入密码") },
        visualTransformation = if (passwordVisible) {
            VisualTransformation.None
        } else {
            PasswordVisualTransformation()
        },
        trailingIcon = {
            IconButton(onClick = { passwordVisible = !passwordVisible }) {
                Icon(
                    imageVector = if (passwordVisible) Icons.Filled.Visibility 
                                else Icons.Filled.VisibilityOff,
                    contentDescription = if (passwordVisible) "隐藏密码" else "显示密码"
                )
            }
        },
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
        modifier = Modifier.fillMaxWidth(),
        colors = TextFieldDefaults.outlinedTextFieldColors(
            focusedBorderColor = MaterialTheme.colors.primary,
            unfocusedBorderColor = MaterialTheme.colors.onSurface.copy(alpha = 0.2f)
        )
    )
}

@Composable
private fun SearchInputField() {
    var query by remember { mutableStateOf("") }
    
    OutlinedTextField(
        value = query,
        onValueChange = { query = it },
        leadingIcon = { 
            Icon(
                Icons.Default.Search, 
                contentDescription = "搜索",
                tint = MaterialTheme.colors.onSurface.copy(alpha = 0.6f)
            ) 
        },
        label = { Text("搜索") },
        placeholder = { Text("输入关键词搜索...") },
        singleLine = true,
        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
        keyboardActions = KeyboardActions(
            onSearch = { /* 执行搜索操作 */ }
        ),
        modifier = Modifier.fillMaxWidth(),
        colors = TextFieldDefaults.outlinedTextFieldColors(
            focusedBorderColor = MaterialTheme.colors.primary,
            unfocusedBorderColor = MaterialTheme.colors.onSurface.copy(alpha = 0.2f)
    )
}

@Composable
private fun CountingInputField(maxLength: Int = 100) {
    var text by remember { mutableStateOf("") }
    
    Column(modifier = Modifier.fillMaxWidth()) {
        OutlinedTextField(
            value = text,
            onValueChange = { if (it.length <= maxLength) text = it },
            modifier = Modifier.fillMaxWidth(),
            label = { Text("带计数的输入") },
            trailingIcon = {
                Text(
                    text = "${text.length}/$maxLength",
                    color = when {
                        text.length > maxLength * 0.9 -> Color.Red
                        else -> MaterialTheme.colors.onSurface.copy(alpha = 0.6f)
                    }
                )
            },
            colors = TextFieldDefaults.outlinedTextFieldColors(
                focusedBorderColor = MaterialTheme.colors.primary,
                unfocusedBorderColor = MaterialTheme.colors.onSurface.copy(alpha = 0.2f)
            )
        )
        
        if (text.length > maxLength * 0.9) {
            Text(
                text = "已接近字数限制",
                color = Color.Red,
                style = MaterialTheme.typography.caption,
                modifier = Modifier.padding(start = 16.dp, top = 4.dp)
            )
        }
    }
}

@Composable
private fun MultiLineInputField() {
    var text by remember { mutableStateOf("") }
    
    OutlinedTextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("多行文本") },
        placeholder = { Text("请输入多行内容...") },
        modifier = Modifier
            .fillMaxWidth()
            .height(150.dp),
        maxLines = 5,
        colors = TextFieldDefaults.outlinedTextFieldColors(
            focusedBorderColor = MaterialTheme.colors.primary,
            unfocusedBorderColor = MaterialTheme.colors.onSurface.copy(alpha = 0.2f)
        )
    )
}

@Composable
private fun DebouncedInputField(delayMillis: Long = 500) {
    var text by remember { mutableStateOf("") }
    var debouncedText by remember { mutableStateOf("") }
    
    LaunchedEffect(text) {
        delay(delayMillis)
        debouncedText = text
        // 这里可以添加实际的处理逻辑
    }
    
    Column(modifier = Modifier.fillMaxWidth()) {
        OutlinedTextField(
            value = text,
            onValueChange = { text = it },
            label = { Text("防抖动输入") },
            placeholder = { Text("输入会延迟处理") },
            modifier = Modifier.fillMaxWidth(),
            colors = TextFieldDefaults.outlinedTextFieldColors(
                focusedBorderColor = MaterialTheme.colors.primary,
                unfocusedBorderColor = MaterialTheme.colors.onSurface.copy(alpha = 0.2f)
            )
        )
        
        Text(
            text = "实际处理的值: $debouncedText",
            style = MaterialTheme.typography.caption,
            modifier = Modifier.padding(top = 8.dp)
        )
    }
}

使用说明

  1. 基础输入框:标准文本输入,带标签和占位符
  2. 密码输入框:支持显示/隐藏密码切换
  3. 搜索输入框:带搜索图标和搜索动作
  4. 带计数输入框:实时显示输入字符数,接近限制时提示
  5. 多行输入框:适合长文本输入,自动扩展高度
  6. 防抖动输入框:延迟处理输入,避免频繁操作

自定义选项

  • 修改 colors 参数可以自定义输入框颜色
  • 调整 modifier 可以改变布局和尺寸
  • 通过 keyboardOptionskeyboardActions 控制键盘行为
  • 使用 visualTransformation 实现特殊输入格式

这个完整解决方案可以直接集成到您的项目中,或根据具体需求进行进一步定制。

你可能感兴趣的:(Compose,compose)