问题描述
在 Jetpack Compose 中构建一个简单的键盘相当简单明了.我使用这个构建了一个非常简单的 KeyRow:
Key.kt
@Composablefun Key(modifier: Modifier = Modifier, label: String, onClick: () -> Unit) {val 形状 = RoundedCornerShape(4.dp)//TODO:使外部可点击但不显示波纹框(修饰符 = 修饰符.填充(2.dp).clip(形状).clickable(onClick = onClick).background(颜色.白色).padding(vertical = 12.dp,horizontal = 4.dp), contentAlignment = Alignment.Center) {文本(文本 = 标签,字体大小 = 20.sp)}}
KeyRow.kt
@Composablefun KeyRow(keys: List) {行(修饰符 = Modifier.fillMaxWidth().background(color = grey200)) {键.forEach {Key(modifier = Modifier.weight(1f), label = it, onClick = { })}}}
这就是它的样子:
我想实现这个动画:
但是,我目前坚持这个
![4]
层次结构
-键盘--KeyRow---按键布局- - 钥匙----KeyPressedOverlay(仅在按下时可见)
我的主要问题是我不知道如何在不使父布局更大的情况下显示 KeyPressedOverlay Composale(比 Key Composable 大).因此,我需要以某种方式溢出父布局.
不确定这是否是最好的方法(可能不是),但我找到了使用 ConstraintLayout
的解决方案...
val keys = listOf(A", B", C", D")约束布局(修饰符 = Modifier.graphicsLayer(clip = false)){val refs = keys.map { createRef() }refs.forEachIndexed { index, ref ->val 修饰符 = 当(索引){0 ->Modifier.constrainAs(ref) {start.linkTo(parent.start)}refs.lastIndex ->Modifier.constrainAs(ref) {start.linkTo(refs[index - 1].end)end.linkTo(parent.end)}否则 ->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)底部链接到(参考底部)}键盘键(键盘键 = 键[索引],修饰符 = 修饰符,修饰符按下 = 修饰符按下)}}
这里的一个重要细节是 graphicLayer(clip = false)
(类似于 View Toolkit 中的 clipChildren
).然后,我为每个键和按下的键创建一个修饰符.注意到 modifierPressed
与另一个修饰符的中心/底部对齐.最后,KeyboardKey
描述如下.
@Composable有趣的键盘键(键盘键:字符串,修饰符:修饰符,修饰符按下:修饰符){var 被记住 { mutableStateOf(false) } 按下文本(键盘键,修饰符.then(修饰符).pressIndicatorGestureFilter(onStart = {pressed = true },onStop = {pressed = false },onCancel = { 按下 = false }).background(颜色.白色).padding(16.dp))如果(按下){文本(键盘键,修饰符.then(modifierPressed).background(颜色.白色).填充(开始 = 16.dp,结束 = 16.dp,顶部 = 16.dp,底部 = 48.dp))}}
这是我得到的结果:
添加更多逻辑,我能够得到这个......
希望这次能有所帮助;)这是要点以防万一......https://gist.github.com/nglauber/4cb1573efba9024c008ea71f38320 Building a simple keyboard is fairly simple and straightforward in Jetpack Compose.I built a really simple KeyRow by using this: Key.kt KeyRow.kt That's what it looks like: I want to achieve this animation: However, I'm currently stuck with this ![4] Hierachy My main problem is that I don't know how to show the KeyPressedOverlay Composale (which is larger than the Key Composable) without making the parent Layout larger. As a result, I need to overflow the parent layout in some way. Not sure if it's the best way (probably not), but I found a solution using One important detail here is This is the result I got: Edit:Adding some more logic, I was able to get this... I hope it helps this time ;)Here's the gist just in case...https://gist.github.com/nglauber/4cb1573efba9024c008ea71f3320b4d8 这篇关于使用 Jetpack Compose 构建软件键盘 - 使用 Jetpack Compose 的 IME 输入法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!@Composable
fun Key(modifier: Modifier = Modifier, label: String, onClick: () -> Unit) {
val shape = RoundedCornerShape(4.dp)
//TODO: make clickable outside but don't show ripple
Box(modifier = modifier
.padding(2.dp)
.clip(shape)
.clickable(onClick = onClick)
.background(Color.White)
.padding(vertical = 12.dp, horizontal = 4.dp), contentAlignment = Alignment.Center) {
Text(text = label, fontSize = 20.sp)
}
}
@Composable
fun KeyRow(keys: List<String>) {
Row(modifier = Modifier.fillMaxWidth().background(color = grey200)) {
keys.forEach {
Key(modifier = Modifier.weight(1f), label = it, onClick = { })
}
}
}
-Keyboard
--KeyRow
---KeyLayout
----Key
----KeyPressedOverlay (only visible when pressed)
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
)
}
}
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
)
)
}
}