kotlin Jetpack compose:TextField with Chips

b1uwtaje  于 7个月前  发布在  Kotlin
关注(0)|答案(1)|浏览(81)


的数据
我试图实现与照片类似的行为。一个可以做同样事情的库也会很有用。我已经尝试了https://github.com/dokar3/ChipTextField,但遇到了一些问题

java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/compose/ui/platform/LocalSoftwareKeyboardController;

字符串

eblbsuwk

eblbsuwk1#

您可以使用FlowRowChipBasicTextField来实现它。


的数据
1-创建保存Uri和String的数据类

@Immutable
data class ChipData(
    val uri: Uri,
    val text: String,
    val id: String = UUID.randomUUID().toString()
)

字符串
2-创建自定义芯片,显示图像,字符串。我使用Coil库的画家从Uri得到Painter

@Composable
private fun MyChip(
    backgroundColor: Color,
    data: ChipData,
    onDeleteClick: () -> Unit
) {
    Chip(
        modifier = Modifier,
        shape = RoundedCornerShape(50),
        enabled = false,
        onClick = {},
        border = BorderStroke(1.dp, Green400.copy(alpha = .9f)),
        colors = ChipDefaults.chipColors(
            disabledBackgroundColor = backgroundColor,
            disabledContentColor = Color.White
        ),
        leadingIcon = {
            Image(
                painter = rememberAsyncImagePainter(data.uri),
                modifier = Modifier
                    .padding(vertical = 4.dp)
                    .size(34.dp)
                    .clip(CircleShape),
                contentScale = ContentScale.FillBounds,
                contentDescription = null
            )
        }
    ) {
        Text(
            text = data.text,
            modifier = Modifier.weight(1f, fill = false),
            overflow = TextOverflow.Ellipsis,
            maxLines = 1
        )
        Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
        Icon(
            modifier = Modifier
                .clip(CircleShape)
                .clickable {
                    onDeleteClick()
                }
                .background(Color.Black.copy(alpha = .4f))
                .size(16.dp)
                .padding(2.dp),
            imageVector = Icons.Filled.Close,
            tint = Color(0xFFE0E0E0),
            contentDescription = null
        )
    }
}


3-使用FlowRow对齐芯片并将BasicTextField放在最后一项。
另外,我使用rememberLauncherForActivityResult来选择可以添加到gradle的图像

implementation("com.google.modernstorage:modernstorage-photopicker:1.0.0-alpha06")


如果需要,可以将其他或默认图像选取器与SAF配合使用

@OptIn(ExperimentalLayoutApi::class)
@Composable
fun ChipAndTextFieldLayout(
    modifier: Modifier = Modifier,
    backgroundColor: Color,
    list: List<ChipData> = emptyList(),
    onChipCreated: (ChipData) -> Unit,
    chip: @Composable (data: ChipData, index: Int) -> Unit
) {

    var text by remember {
        mutableStateOf("")
    }

    val focusRequester = remember {
        FocusRequester()
    }

    val keyboardController: SoftwareKeyboardController? = LocalSoftwareKeyboardController.current

    val photoPicker =
        rememberLauncherForActivityResult(PhotoPicker()) { uris ->
            uris.firstOrNull()?.let { uri: Uri ->
                onChipCreated(
                    ChipData(
                        uri = uri,
                        text = text
                    )
                )
                text = ""
                // Open keyboard after new chip is added
                keyboardController?.show()
            }
        }

    LaunchedEffect(Unit) {
        delay(100)
        focusRequester.requestFocus()
    }

    FlowRow(
        modifier = modifier
            .drawWithContent {
                drawContent()
                drawLine(
                    Green400.copy(alpha = .6f),
                    start = Offset(0f, size.height),
                    end = Offset(size.width, size.height),
                    strokeWidth = 4.dp.toPx()
                )
            },
        horizontalArrangement = Arrangement.spacedBy(6.dp)
    ) {

        list.forEachIndexed { index, item ->
            key(item.id) {
                chip(item, index)
            }
        }

        Box(
            modifier = Modifier.height(54.dp)
                // This minimum width that TextField can have
                // if remaining space in same row is smaller it's moved to next line
                .widthIn(min = 80.dp)
                // TextField can grow as big as Composable width
                .weight(1f),
            contentAlignment = Alignment.CenterStart
        ) {
            BasicTextField(
                modifier = Modifier.focusRequester(focusRequester),
                value = text,
                textStyle = TextStyle(
                    fontSize = 20.sp
                ),
                cursorBrush = SolidColor(backgroundColor),
                singleLine = true,
                onValueChange = { text = it },
                keyboardOptions = KeyboardOptions(
                    imeAction = ImeAction.Done
                ),
                keyboardActions = KeyboardActions(
                    onDone = {
                        if (text.isNotEmpty()) {
                            keyboardController?.hide()
                            photoPicker.launch(
                                PhotoPicker.Args(
                                    PhotoPicker.Type.IMAGES_ONLY, 1
                                )
                            )
                        }
                    }
                )
            )
        }
    }
}


使用

@Preview
@Composable
private fun ChipSampleAndTextLayoutSample() {

    val backgroundColor = Green400.copy(alpha = .6f)

    val chipDataSnapshotStateList = remember {
        mutableStateListOf<ChipData>()
    }

    ChipAndTextFieldLayout(
        modifier = Modifier.fillMaxWidth().padding(8.dp),
        list = chipDataSnapshotStateList,
        backgroundColor = backgroundColor,
        onChipCreated = {
            chipDataSnapshotStateList.add(it)
        },

        chip = { data: ChipData, index: Int->
            MyChip(backgroundColor, data){
                chipDataSnapshotStateList.removeAt(index)
            }
        }
    )
}

相关问题