我怎样才能在android compose kotlin中进行一键拖动和多点触摸拖动

发布于 2025-01-10 14:52:39 字数 1092 浏览 2 评论 0原文

我想移动 Box 一键拖动和多点触摸拖动,但是,它只能移动多点触摸。 我如何使用一个偏移变量来使用它们

@Composable
fun TransformableSample() {
    // set up all transformation states
    var scale by remember { mutableStateOf(1f) }
    var rotation by remember { mutableStateOf(0f) }
    var offset by remember { mutableStateOf(Offset.Zero) }
    val state = rememberTransformableState { zoomChange, offsetChange, rotationChange ->
        scale *= zoomChange
        rotation += rotationChange
        offset += offsetChange
    }
    Box(
        Modifier
            // apply other transformations like rotation and zoom
            // on the pizza slice emoji
            .graphicsLayer(
                scaleX = scale,
                scaleY = scale,
                rotationZ = rotation,
                translationX = offset.x,
                translationY = offset.y
            )
            // add transformable to listen to multitouch transformation events
            // after offset
            .transformable(state = state)
            .background(Color.Blue)
            .fillMaxSize()
    )
}

I want to move Box one touch drag and multi touch drag, however, it only moves multitouch.
How can I use both of them using one offset variable

@Composable
fun TransformableSample() {
    // set up all transformation states
    var scale by remember { mutableStateOf(1f) }
    var rotation by remember { mutableStateOf(0f) }
    var offset by remember { mutableStateOf(Offset.Zero) }
    val state = rememberTransformableState { zoomChange, offsetChange, rotationChange ->
        scale *= zoomChange
        rotation += rotationChange
        offset += offsetChange
    }
    Box(
        Modifier
            // apply other transformations like rotation and zoom
            // on the pizza slice emoji
            .graphicsLayer(
                scaleX = scale,
                scaleY = scale,
                rotationZ = rotation,
                translationX = offset.x,
                translationY = offset.y
            )
            // add transformable to listen to multitouch transformation events
            // after offset
            .transformable(state = state)
            .background(Color.Blue)
            .fillMaxSize()
    )
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

纵情客 2025-01-17 14:52:40

您将需要使用 Modifier.pointerInput() 与Modifier.graphicsLayer()。对您来说重要的是,这将允许您用一根手指或两根手指拖动图像。它仍然会使用记住状态(尽管我通常保存这些值以及 ViewModel 中的所有数学)。这是从文档中复制的代码。

import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTransformGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput

/**
 * Rotates the given offset around the origin by the given angle in degrees.
 *
 * A positive angle indicates a counterclockwise rotation around the right-handed 2D Cartesian
 * coordinate system.
 *
 * See: [Rotation matrix](https://en.wikipedia.org/wiki/Rotation_matrix)
 */
fun Offset.rotateBy(angle: Float): Offset {
   val angleInRadians = angle * PI / 180
   return Offset(
      (x * cos(angleInRadians) - y * sin(angleInRadians)).toFloat(),
      (x * sin(angleInRadians) + y * cos(angleInRadians)).toFloat()
   )
}

var offset by remember { mutableStateOf(Offset.Zero) }
var zoom by remember { mutableStateOf(1f) }
var angle by remember { mutableStateOf(0f) }

Box(
   Modifier
      .pointerInput(Unit) {
         detectTransformGestures(
            onGesture = { centroid, pan, gestureZoom, gestureRotate ->
               val oldScale = zoom
               val newScale = zoom * gestureZoom

               // For natural zooming and rotating, the centroid of the gesture should
               // be the fixed point where zooming and rotating occurs.
               // We compute where the centroid was (in the pre-transformed coordinate
               // space), and then compute where it will be after this delta.
               // We then compute what the new offset should be to keep the centroid
               // visually stationary for rotating and zooming, and also apply the pan.
               offset = (offset + centroid / oldScale).rotateBy(gestureRotate) -
                   (centroid / newScale + pan / oldScale)
               zoom = newScale
               angle += gestureRotate
            }
         )
      }
      .graphicsLayer {
         translationX = -offset.x * zoom
         translationY = -offset.y * zoom
         scaleX = zoom
         scaleY = zoom
         rotationZ = angle
         transformOrigin = TransformOrigin(0f, 0f)
      }
      .background(Color.Blue)
      .fillMaxSize()
)

You're going to want to use a Modifier.pointerInput() combined with Modifier.graphicsLayer(). The important thing for you is that this will let you drag your image around with one finger or with two fingers. It'll still use the remember states (although I usually hold these values as well as all the math in my ViewModel). Here's the code copied from the documentation.

import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTransformGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput

/**
 * Rotates the given offset around the origin by the given angle in degrees.
 *
 * A positive angle indicates a counterclockwise rotation around the right-handed 2D Cartesian
 * coordinate system.
 *
 * See: [Rotation matrix](https://en.wikipedia.org/wiki/Rotation_matrix)
 */
fun Offset.rotateBy(angle: Float): Offset {
   val angleInRadians = angle * PI / 180
   return Offset(
      (x * cos(angleInRadians) - y * sin(angleInRadians)).toFloat(),
      (x * sin(angleInRadians) + y * cos(angleInRadians)).toFloat()
   )
}

var offset by remember { mutableStateOf(Offset.Zero) }
var zoom by remember { mutableStateOf(1f) }
var angle by remember { mutableStateOf(0f) }

Box(
   Modifier
      .pointerInput(Unit) {
         detectTransformGestures(
            onGesture = { centroid, pan, gestureZoom, gestureRotate ->
               val oldScale = zoom
               val newScale = zoom * gestureZoom

               // For natural zooming and rotating, the centroid of the gesture should
               // be the fixed point where zooming and rotating occurs.
               // We compute where the centroid was (in the pre-transformed coordinate
               // space), and then compute where it will be after this delta.
               // We then compute what the new offset should be to keep the centroid
               // visually stationary for rotating and zooming, and also apply the pan.
               offset = (offset + centroid / oldScale).rotateBy(gestureRotate) -
                   (centroid / newScale + pan / oldScale)
               zoom = newScale
               angle += gestureRotate
            }
         )
      }
      .graphicsLayer {
         translationX = -offset.x * zoom
         translationY = -offset.y * zoom
         scaleX = zoom
         scaleY = zoom
         rotationZ = angle
         transformOrigin = TransformOrigin(0f, 0f)
      }
      .background(Color.Blue)
      .fillMaxSize()
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文