I'm trying to build a panel that contains a lot of information. Those informations must be selectable, in order to able the user to copy it. But, beyond this, this information panel contains some parts that, when clicked, must to perform something like a button click (such as navigation, alert, etc).
My problem is that, even properly building an AnnotatedString
that annotates the clickable parts and setting it to a ClickableText
, if I put it inside a SelectionContainer
I can select the text but I can not to click the desired clickable parts (most probably due to multiple clicks handling under the hood).
To illustrate, following have an example of text that should be presented:
Date: 99/99/9999
Count: 99999
max: xxxx
min: xxxx
mean: xxxx
...
The "xxxx" are an example of items that should be clickable.
Then, putting it to a ClickableText
and, by its time, inside a SelectionContainer
the text is selectable, but not clickable in the "xxxxx" parts. The AnnotatedString
was built as described in here.
Note that this can be achieved by forgeting the ClickableText
and building all this information panel using components separately. However I'm wondering how to do this using the existing resources of the API, such as AnnotatedString
, ClickableText
and SelectableContainer
.
Also, if there are another better solution to do that, feel free to show us.
Build your own tap gesture and consume touch on demand:
suspend fun PointerInputScope.detectTapGestureIfMatch(
onTap: (Offset) -> Boolean,
) {
awaitEachGesture {
awaitFirstDown()
val up = waitForUpOrCancellation()
if (up != null && onTap(up.position)) {
up.consume()
}
}
}
You can check out this answer on how to add tagged annotations to your text and process them when clicked. Then, if you find an annotation, you can do your action and return true
so it'll be consumed, otherwise return false
- and SelectableText
will get that touch.
modifier = Modifier
.pointerInput(Unit) {
detectTapGestureIfMatch { position ->
val annotation = layoutResult
?.getOffsetForPosition(position)
?.let { offset ->
annotatedString.getStringAnnotations(
start = offset,
end = offset,
tag = "clickableTag",
).firstOrNull()
}
if (annotation != null) {
uriHandler.openUri(annotation.item)
true
} else {
false
}
}
}