I have a code, that draws a line from the box to the cursor. Everything worked well, until I decided to Modulize the code from the monolith. Motion event gives incorrect values of y coordinate of cursor.
Here is the code I use to draw:
val positions = remember {
mutableStateMapOf<Position, Position>()
}
val list = remember {
mutableStateListOf<PositionRange>()
}
Canvas(modifier = Modifier.fillMaxSize(), onDraw = {
positions.forEach {
val startPosition = it.key
val endPosition = it.value
if (startPosition.isNotEmpty() && endPosition.isNotEmpty()) {
this.drawLine(
Color.Black,
Offset(startPosition.x, startPosition.y),
Offset(endPosition.x, endPosition.y),
10f,
StrokeCap.Round,
)
}
}
})
Here how I take position of the touch:
@Composable
private fun FromBox(
list: MutableList<PositionRange>,
onDragLineEvent: (Pair<Position, Position>) -> Unit,
) {
var startPosition by Position.rememberEmptyPosition()
var endPosition by Position.rememberEmptyPosition()
Box(
modifier = Modifier
.onGloballyPositioned {
val size = it.size
val coords = it.positionInRoot()
val posRange =
PositionRange(coords.toPosition(), size.width.toFloat(), size.height.toFloat())
startPosition = posRange.getCenter()
onDragLineEvent(startPosition to endPosition)
}
.pointerInteropFilter {
if (it.pointerCount == 1) {
when (it.action) {
MotionEvent.ACTION_MOVE -> {
val pos = Position(it.x, it.y)
list.forEach { posRange ->
if (posRange.inRange(pos)) {
val center = posRange.getCenter()
endPosition = endPosition.copy(
x = center.x,
y = center.y
)
onDragLineEvent(startPosition to endPosition)
return@forEach
} else {
endPosition = endPosition.copy(x = pos.x, y = pos.y)
onDragLineEvent(startPosition to endPosition)
}
}
}
MotionEvent.ACTION_UP,
MotionEvent.ACTION_CANCEL,
-> {
endPosition = Position.EMPTY
onDragLineEvent(startPosition to endPosition)
}
}
} else {
endPosition = Position.EMPTY
}
true
}
)
}
Position
and PositionRange
is just data classes with extra functions like
fun inRange(position: Position): Boolean {
val topEnd = Position(startPoint.x + width, startPoint.y)
val bottomEnd = Position(startPoint.x, startPoint.y + height)
val endPos = Position(startPoint.x + width, startPoint.y + height)
return (position.x >= startPoint.x && position.y >= startPoint.y) &&
(position.x <= topEnd.x && position.y >= topEnd.y) &&
(position.x >= bottomEnd.x && position.y <= bottomEnd.y) &&
(position.x <= endPos.x && position.y <= endPos.y)
}
fun getCenter(): Position {
return Position(startPoint.x + width / 2, startPoint.y + height / 2)
}
Here is how it draws:
The solution is not the best, but at least it works.
Get your coordinate like this:
MotionEvent.ACTION_MOVE -> {
val pos = Position(it.x, it.rawY - it.yPrecision * 4.5f)
...
}