Kebbin
12/05/2021, 10:10 AM.isTertiaryPressed
) button anymore.
I was using the Modifier.pointerInput(Unit)
in 1.0.0-beta5 with Kotlin 1.5.31, and tried just dropping the Compose -beta5
in my Gradle file to upgrade to the release version.
I also tried .onPointerEvent(PointerEventType.Press)
in 1.0.0, but still it doesn't work.
The scroll wheel rotation still works, and the Primary button presses OK.
When pressing the wheel button while holding the Primary button down first, my debugging will show that the middle button is being pressed OK, but my conditional code is not running.Igor Demin
12/05/2021, 10:19 AMimport androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.*
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.singleWindowApplication
@OptIn(ExperimentalComposeUiApi::class)
fun main() = singleWindowApplication {
var text by remember { mutableStateOf("Press me") }
Box(
Modifier
.fillMaxSize()
.onPointerEvent(PointerEventType.Press) {
val position = it.changes.first().position
text = when {
it.buttons.isPrimaryPressed && it.buttons.isTertiaryPressed -> "Left+Middle click $position"
it.buttons.isPrimaryPressed -> "Left click $position"
it.buttons.isTertiaryPressed -> "Middle click $position"
else -> text
}
},
contentAlignment = Alignment.Center
) {
Text(text, fontSize = 30.sp)
}
}
Kebbin
12/05/2021, 10:21 AMIgor Demin
12/05/2021, 10:21 AMbut my conditional code is not runningcould your show the condition code?
Kebbin
12/05/2021, 10:22 AM// .onPointerEvent(PointerEventType.Press) {
// val clicks = it.buttons
// val keys = it.keyboardModifiers
// val wheelBtn = clicks.isTertiaryPressed
// val ctrlBtn = keys.isCtrlPressed
//
// val pan = it.calculatePan()
//
// val panning = wheelBtn && !ctrlBtn
// val rotating = wheelBtn && ctrlBtn
//
// if (panning) offset += pan
//
// if (rotating) {
// rotationZ -= pan.x
// rotationX += pan.y
// if (rotationX > maxTilt) rotationX = maxTilt
// if (rotationX < minTilt) rotationX = minTilt
// if (rotationZ > 180) rotationZ -= 360
// if (rotationZ < -179) rotationZ += 360
// }
//
// // This resets the view in case of mad pan-zoom-rotes!
// if (clicks.isPrimaryPressed) {
// scale = 1f
// rotationX = 0f
// rotationZ = 0f
// offset = Offset.Zero
// }
//
// }
.onPointerEvent()
code wouldn't work when I tried going back to -beta5.Igor Demin
12/05/2021, 10:30 AMif (clicks.isPrimaryPressed) {It should be
if (!panning && !rotating && clicks.isPrimaryPressed) {
When we click with the wheel button, and the left button is still pressed, isPrimaryPressed
will return true
We have fixed a bug, when onPointerEvent/pointerEvent wrongly reported pressed buttons, so it is probably because of that your code behaves differently in 1.0.0.Kebbin
12/05/2021, 10:31 AMIgor Demin
12/05/2021, 10:31 AMif (!panning && !rotating && clicks.isPrimaryPressed)or not. one minute 🙂
Kebbin
12/05/2021, 10:31 AM.pointerInput(Unit) {
forEachGesture {
awaitPointerEventScope {
awaitFirstDown()
do {
val event = awaitPointerEvent()
val clicks = event.buttons
val keys = event.keyboardModifiers
val wheelBtn = clicks.isTertiaryPressed
val ctrlBtn = keys.isCtrlPressed
val pan = event.calculatePan()
val panning = wheelBtn && !ctrlBtn
val rotating = wheelBtn && ctrlBtn
if (panning) offset += pan
if (rotating) {
rotationZ -= pan.x
rotationX += pan.y
if (rotationX > maxTilt) rotationX = maxTilt
if (rotationX < minTilt) rotationX = minTilt
if (rotationZ > 180) rotationZ -= 360
if (rotationZ < -179) rotationZ += 360
}
// This resets the view in case of mad pan-zoom-rotes!
if (clicks.isPrimaryPressed) {
scale = 1f
rotationX = 0f
rotationZ = 0f
offset = Offset.Zero
}
println("$wheelBtn $ctrlBtn")
//println("Pan $panning Rot $rotating rotX $rotationX rotZ $rotationZ")
//println("Pan $pan Pan2 $pan2 Dist $panDist Dir ${panDir * 180 / PI} Scale $scale rotX $rotationX rotZ $rotationZ")
} while (event.changes.any { it.pressed })
}
}
}
Igor Demin
12/05/2021, 10:38 AMif (clicks.isPrimaryPressed && !isPrimaryPressedPrevious) {
println("reset")
}
isPrimaryPressedPrevious = clicks.isPrimaryPressed
Where isPrimaryPressedPrevious
is:
var isPrimaryPressedPrevious by remember { mutableStateOf(false) }
It is somewhat inconvenient, but probably this is the only way, when we need to work with multiple pressed buttons.Kebbin
12/05/2021, 10:40 AMIgor Demin
12/05/2021, 10:41 AMthe wheel button was causing no response.not sure, but that is probably because we reset after we try to rotate
Kebbin
12/05/2021, 10:41 AM.forEachGesture
code that I got from a sample online? Separating out each click as a separate event?Igor Demin
12/05/2021, 10:44 AMif (rotating)
condition, but after that we execute code in if (clicks.isPrimaryPressed)
condition, which sets rotationZ/rotationX to 0.0Kebbin
12/05/2021, 10:46 AMIgor Demin
12/05/2021, 10:46 AMprobably, it checks the state offorEachGesture
it.changes.first().changedToDown()
. and we had a bug in it, when we press multiple buttons.it still doesn't do anythingOh, in that case, it is something else.
Kebbin
12/05/2021, 10:47 AM.onPointerEvent
code I wrote.
Which should I be using? .onPointerEvent
or .pointerInput
?Oh, in that case, it is something else.Found it! 🤓 OK, well I'll have to leave it with you mate! Goodnight!
Igor Demin
12/05/2021, 10:52 AMonPointerEvent
is basically a simplified pointerInput
(you can look at the code inside). I would recommend to use onPointerEvent
(pointerInput
can be helpful for more complex event handling, that is based on couroutines)
Also, forEachGesture
doesn't work well with multiple pressed buttons, so I suggest to avoid it.Kebbin
12/05/2021, 10:53 AMIgor Demin
12/05/2021, 10:53 AMAs a side note, how do you do that Quote Reply business you've done there?Just type ">", and Slack transforms it to quote 🙂
Kebbin
12/05/2021, 10:54 AMCool!
code.segment
Quote!
.onPointerEvent(PointerEventType.Move) {
instead of .Press)
!!
I discovered all the buttons and keyModifiers were working fine, but I was getting no .calculatePan()
, so I looked into the PointerEventTypes available.
Looks like I might be able to use the .Scroll
to detect the mouse wheel, instead of .mouseScrollFilter
? What would you recommend?
Also on that thought, is there any issue with having multiple .onPointerEvent
modifiers, or is that just the way to do it? I guess it is the only option, as you'd need different types of PointerEventType
parameters for different input types....Igor Demin
12/07/2021, 9:46 AMI needed to useOh, right, the small detail that didn’t catch an eye 🙂instead of.onPointerEvent(PointerEventType.Move) {
.Press)
Looks like I might be able to use theto detect the mouse wheel, instead of.Scroll
? What would you recommend?.mouseScrollFilter
mouseScrollFilter
will be deprecated in 1.1 or in 1.2, better to use .Scroll
.
or is that just the way to do itYes, that is the way in which
.onPointerEvent
should be used. Each onPointerEvent
creates a separate coroutine, so if your application is big, it can create 500 coroutines instead of 200 (if we would use pointerInput
). And it doesn’t sound scary, because coroutines are lightweight.Kebbin
12/07/2021, 9:46 AM.Scroll
now....PointerEventType.Scroll
is what I'm working on now. I thought you meant a .Scroll modifier! 🥴