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:
- When I type "@" with the keyboard/press a button, a list of members is displayed.
- When I select a member from the list, their name will be inserted into the TextField in the format @{memberName}
- 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:
- 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)
)
- 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.