Skip to content Skip to sidebar Skip to footer

Build Software Keyboard With Jetpack Compose - Ime Input Method With Jetpack Compose

Building a simple keyboard is fairly simple and straightforward in Jetpack Compose. I built a really simple KeyRow by using this: Key.kt @Composable fun Key(modifier: Modifier = Mo

Solution 1:

Not sure if it's the best way (probably not), but I found a solution using ConstraintLayout...

val keys = listOf("A", "B", "C", "D")
ConstraintLayout(
    modifier = Modifier.graphicsLayer(clip = false)
) {
    val refs = keys.map { createRef() }
    refs.forEachIndexed { index, ref ->
        val modifier = when (index) {
            0 -> Modifier.constrainAs(ref) {
                start.linkTo(parent.start)
            }
            refs.lastIndex -> Modifier.constrainAs(ref) {
                start.linkTo(refs[index - 1].end)
                end.linkTo(parent.end)
            }
            else -> Modifier.constrainAs(ref) {
                start.linkTo(refs[index - 1].end)
                end.linkTo(refs[index + 1].start)
            }
        }
        val modifierPressed = Modifier.constrainAs(createRef()) {
            start.linkTo(ref.start)
            end.linkTo(ref.end)
            bottom.linkTo(ref.bottom)
        }
        KeyboardKey(
            keyboardKey = keys[index],
            modifier = modifier,
            modifierPressed = modifierPressed
        )
    }
}

One important detail here is graphicLayer(clip = false) (which is similar to the clipChildren in View Toolkit). Then, I'm creating a modifier to each key and to the pressed key. Noticed that the modifierPressed is aligned to the center/bottom of the other modifier. Finally the KeyboardKey is described below.

@Composable
fun KeyboardKey(
    keyboardKey: String,
    modifier: Modifier,
    modifierPressed: Modifier
) {
    var pressed by remember { mutableStateOf(false) }
    Text(keyboardKey, Modifier
        .then(modifier)
        .pressIndicatorGestureFilter(
            onStart = { pressed = true },
            onStop = { pressed = false },
            onCancel = { pressed = false }
        )
        .background(Color.White)
        .padding(16.dp)
    )
    if (pressed) {
        Text(
            keyboardKey, Modifier
                .then(modifierPressed)
                .background(Color.White)
                .padding(
                    start = 16.dp, 
                    end = 16.dp, 
                    top = 16.dp, 
                    bottom = 48.dp
                )
        )
    }
}

This is the result I got: Keyboard effect

Edit: Adding some more logic, I was able to get this... enter image description here

I hope it helps this time ;) Here's the gist just in case... https://gist.github.com/nglauber/4cb1573efba9024c008ea71f3320b4d8

Solution 2:

I guess you're looking for the pressIndicatorGestureFilter modifier... I tried this and worked for me...

var pressed by remember { mutableStateOf(false) }
valpadding=if (pressed) 32.dp else16.dp
Text("A", Modifier
    .pressIndicatorGestureFilter(
        onStart = {
            pressed = true
        },
        onStop = {
            pressed = false
        },
        onCancel = {
            pressed = false
        }
    )
    .background(Color.White)
    .padding(start = 16.dp, end = 16.dp, top = padding, bottom = padding)
)

Post a Comment for "Build Software Keyboard With Jetpack Compose - Ime Input Method With Jetpack Compose"