1

This is my scenario, I need to get text value of clicked text:

@Composable
fun keyboard(){
    val letters: Array<Pair<String, String>> = letterMap.toList().toTypedArray();
    val txtModifier = Modifier
        .clickable(onClick = { btnTapAction( /* send a letter */ ) })
    for(i in 0..3)
        Row(){
            for(j in (i*8)..(i*8+7))
                if (j<30)
                    Text(letters[j].first, txtModifier)
        }
}

I have 30 Text's, each containing one cyrillic letter, they act like keyboard buttons, and I want to send clicked letter to function btnTapAction() which handles entered letters.

I have looked at documentation and I could not find a way to do it, but I hope it can be done?

Milos
  • 168
  • 2
  • 12

1 Answers1

3

If you wish to return value of clicked item create a separate Composable using state-hoisting

@Composable
fun Keyboard(){
    val letters: Array<Pair<String, String>> = letterMap.toList().toTypedArray();
    val txtModifier = Modifier// You can do some styling here such as rounded shape, etc

    for(i in 0..3)
        Row(){
            for(j in (i*8)..(i*8+7))
                if (j<30)
                    Letter( txtModifier, letters[j].first){char:String->
                        // You can pass this letter from keyboard to parent Composable using another callback or process here
                    }
        }
}


@Composable
private fun Letter(modifier: Modifier = Modifier, char: String, onClick: (String) -> Unit) {
    Text(text = char,
        modifier = modifier.clickable {
            onClick(char)
        }
    )
}

Edit

Initial question was like a question to get position of a letter in a Text, you wish to get position of any character inside a Text you can use answer below

You can use ClickableText Composable to get position of click

val context = LocalContext.current
val text = "Some clickable text"

ClickableText(

    text = buildAnnotatedString {
        append(text)
    },
    onClick = { position: Int ->
        Toast.makeText(
            context,
            text.substring(startIndex = 0, endIndex = position),
            Toast.LENGTH_SHORT
        ).show()
    }
)
Thracian
  • 43,021
  • 16
  • 133
  • 222
  • Hey Doctor Thrace, could you explain what the `Int` parameter of the `onClick` lambda actually returns? I mean it can't return the position/index of the `Text` within a list right out-of-the-box. [The Documentation](https://developer.android.com/reference/kotlin/androidx/compose/foundation/text/package-summary#ClickableText(androidx.compose.ui.text.AnnotatedString,androidx.compose.ui.Modifier,androidx.compose.ui.text.TextStyle,kotlin.Boolean,androidx.compose.ui.text.style.TextOverflow,kotlin.Int,kotlin.Function1,kotlin.Function1)) is confusing as an illusion. It says `Int` and types `Offset`. – Richard Onslow Roper Sep 11 '22 at 04:03
  • Do we have a choice of parameter which we can configure by explicitly specifying an object type in front of the parameter? My Computer is dead since yesterday so I can't figure anything out on my own. It's really sad if I think about it now... – Richard Onslow Roper Sep 11 '22 at 04:06
  • @RichardOnslowRoper it returns index of character you clicked in String. What i get from question is how you get value of clicked position. `I need to get text value of clicked text`. My answer above returns substring from start of the text to clicked character of the text – Thracian Sep 11 '22 at 05:54
  • My Android Studio complains about the "text" used within onClick: "Unresolved reference: text" – Milos Sep 11 '22 at 11:51
  • `val text = "Some clickable text"` is a sample text for demonstration – Thracian Sep 11 '22 at 11:53
  • Oh but I actually need to provide the whole text of the clicket Text component to the click handler, whatever that text might be. I have 30 Text's and whichever gets tapped, has to send it's string to the click handler. I am sorry for the confusion. – Milos Sep 11 '22 at 12:08
  • If you post more code about how you display or send these texts i might be able to provide more. You can display each text with `ClickableText ` instead of `Text`. Your example above shows one `Text` being clicked. Using `ClickableText` or Text with `Modifier.pointerInput` and getting touch position and using this position with `onTextLayout` is same are same thing however `ClickableText` is by far the least effortless – Thracian Sep 11 '22 at 12:30
  • I've edited my code, it looks more like this, I dislike button shape, I cannot control it well, and I want to use Text's instead of buttons. – Milos Sep 11 '22 at 14:15
  • 1
    @Milos updated my answer – Thracian Sep 11 '22 at 15:01