1

I am a newbie in Android Jetpack Compose and today I have a task that requires to create a TextField with mention. Please see my description.

What I need to do:

  1. When I type "@" with the keyboard/press a button, a list of members is displayed.
  2. When I select a member from the list, their name will be inserted into the TextField in the format @{memberName}
  3. Member's name is bold, Green color.

What I have done: I did 1, 2

The problems I encountered: I've done thing 3 but it's not perfect. TextFieldValue(annotatedString) seems a viable choice in my case. When I selected a member from the list, I succeeded in styling the member's name. But when I continued to enter text, that styling was gone.Video description

Here is my code:

  1. The logic when I click on a item in list member:
val currentCursorIndex = currentMessage.selection.start
                                            val newString = currentMessage.text.replaceRange(
                                                startMentionKeyWordIndex,
                                                currentCursorIndex,
                                                "${it.name} "
                                            )

                                            // Find my regex to Bold and Green
                                            val regex = Regex("@\\S+\\s")
                                            val annotatedString = buildAnnotatedString {
                                                val matches = regex.findAll(newString)
                                                var lastIndex = 0
                                                matches.forEach { match ->
                                                    val range = match.range
                                                    val boldStyle = SpanStyle(fontWeight = FontWeight.Bold, color = Green)
                                                    append(newString.substring(lastIndex, range.first))
                                                    withStyle(boldStyle) {
                                                        append(newString.substring(range))
                                                    }
                                                    lastIndex = range.last + 1
                                                }
                                                if (lastIndex < newString.length) {
                                                    append(newString.substring(lastIndex))
                                                }
                                            }

                                            // Set annotatedString to State of TextField
                                            currentMessage = TextFieldValue(
                                                annotatedString = annotatedString,
                                                selection = TextRange(currentCursorIndex + it.name.length + 1)
                                            )
  1. My TextField:
TextField(
                    value = currentMessage,
                    onValueChange = {
                        callBack(ChatInputAction.OnTextChange(it))
                    },
                    textStyle = TextStyle(fontSize = 18.sp, color = Gray1),
                    placeholder = {
                        Text(
                            text = stringResource(id = R.string.reply),
                            fontSize = 18.sp,
                            color = Gray1
                        )
                    },
                    colors = TextFieldDefaults.textFieldColors(
                        containerColor = Color.Transparent,
                        unfocusedIndicatorColor = Color.Transparent,
                        focusedIndicatorColor = Color.Transparent
                    ),
                    maxLines = 5,
                    modifier = Modifier
                        .fillMaxWidth()
                        .weight(1f)
                        .focusRequester(focusRequester)
                        .onFocusChanged {
                            callBack(ChatInputAction.OnFocusChange)
                        }
                )

Please let me know if you have any ideas. I am very grateful for that.

Ta Van Co
  • 11
  • 2

0 Answers0