简体   繁体   中英

Jetpack Compose: Usage of Offset in PointerScope

I'm having issues understanding how exactly Offset works in Compose, specifically in the PointerScope onTap callback function to track the exact location where the user tapped on a UI element.

Use Case

User is presented an image. Whenever the user taps onto the image, a marker icon is placed on the tapped location.

Code

(You can ignore the button here, it does nothing at this point)

class MainActivity : ComponentActivity() {

//private var editMode = false

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContent {

        val offset = remember {
            mutableStateOf(Offset.Infinite)
        }

        MyLayout(offset.value) {
            offset.value = it
        }
    }
}

@Composable
private fun MyLayout(
    offset: Offset,
    saveLastTap: (Offset) -> Unit
) {
    val painter: Painter = painterResource(id = R.drawable.landscape)

    Column(Modifier.fillMaxSize()) {

        Box(
            modifier = Modifier
                .weight(0.95f)
                .fillMaxSize()
        ) {
            Image(
                contentScale = FillBounds,
                painter = painter,
                contentDescription = "",
                modifier = Modifier
                    .pointerInput(Unit) {
                    detectTapGestures(
                        onTap = {
                            saveLastTap(it)
                        }
                    )
                }.border(5.dp, Color.Red)
            )
            
            if (offset.isFinite) {
                PlaceMarkerOnImage(offset = offset)
            }
        }
        Button(
            enabled = false,
            onClick = { TODO("Button Impl") },
            modifier = Modifier.weight(0.05f),
            shape = MaterialTheme.shapes.small
        ) {
            Text(text = "Edit Mode")
        }

    }
}

@Composable
private fun PlaceMarkerOnImage(offset: Offset) {
    Image(
        painter = painterResource(id = R.drawable.marker),
        contentScale = ContentScale.Crop,
        contentDescription = "",
        modifier = Modifier.offset(offset.x.dp, offset.y.dp)
    )
}
}

Outcome

I added a little dot to the screenshots to indicate where i tapped. You see the image is getting placed far off the expected locations

截图1 截图2

Assumptions

I read a bit about the Offset object and i suspect the difference has something to do with the conversion to .dp which i need to feed the offset to the marker image Modifier .

It might also be related to coordinates being related to it's parent views or something, but since in my example theres nothing else in the UI but the image, i can't grasp this as a possible candidate.

Any help appreciated. Thank you !

I just solved it by replacing

modifier = Modifier.offset( offset.x.dp, offset.y.dp )

with

modifier = Modifier.offset(
     x= LocalDensity.current.run{offset.x.toInt().toDp()},
     y= LocalDensity.current.run{offset.y.toInt().toDp()} )

Turned out my mistake was that I ignored the properties of dp by just casting the pixel value to dp. Instead, I should call the local device density to correctly determine the amount of pixels for the transformation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM