“This is the 21st day of my participation in the First Challenge 2022. For details: First Challenge 2022”
Compose comes across a feature for browsing images that zooms in and out with two fingers
knowledge
Modifier.offset
The Modifier offset can offset the content. The offset can be positive or non-positive. Applying an offset only changes the position of the content and does not affect its size measurement.
Offset Indicates the offset that changes due to user interaction. It avoids recompilation when offsets change, and adds a graphical layer to prevent unnecessary redrawing of context when offsets change.
graphicsLayer
Draws content to elements in the draw layer. The drawing layer can be invalidated separately from the parent layer. When content is updated independently of anything above, graphicsLayer should be used to minimize invalid content.
GraphicsLayer can be used to apply various effects to content
- Scaling (scaleX, scaleY)
- Rotation (rotationX, rotationY, rotationZ)
- Opacity (alpha)
- Shadowed evation, Shape
- Clip, Shape
- And using Renderefect to change the result of the layer.
Officially, if you provide a non-zero shadow elevation and pass a concave shape, the shadow will not be drawn on Android versions less than 10.
An alpha value of less than 1.0f will implicitly crop its content to its boundaries. This is because an intermediate compositing layer is created to render the content into FIRST before drawing it to the target with the required alpha. The size of this layer is the same as the boundaries of the composable objects on which the modifier is configured, and anything outside these boundaries is ignored.
Modifier.pointerInput
Used to handle pointer input within the modified element area. Extension functions on PointerInputScope or AwaitPointerEventScope can be defined to perform higher levels of gesture detection. The pointer input processing block is cancelled and restarted when the pointer input is recombined with a different key 1.
PointerInputScope.detectTransformGestures
Gesture detector for rotation, panning, and zooming. OnGeture is called when any rotation, scaling, or translation occurs, passing the rotation Angle in degrees, amplifying the scale factor in pixels, and translating by offsets.
The logical explanation
Define four variables
var angle by remember { mutableStateOf(0f)}// The rotation Angle
var zoom by remember { mutableStateOf(1f)}/ / zoom
var offsetX by remember { mutableStateOf(0f)}// The X offset
var offsetY by remember { mutableStateOf(0f)}// The X offset
Copy the code
offset
Modifier
.offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
Copy the code
Put it in graphicsLayer
.graphicsLayer(
scaleX = zoom,
scaleY = zoom,
rotationZ = angle
)
Copy the code
Listening to the gestures
And then I’m going to listen for the gesture, get the value that the swipe returns and have the mutableStateOf tell graphicsLayer to refresh the UI
.pointerInput(Unit) {
detectTransformGestures(
onGesture = { _, pan, gestureZoom, gestureRotate ->
angle += gestureRotate
zoom *= gestureZoom
offsetX += pan.x
offsetY += pan.y
}
)
}
Copy the code
For an Image, just put an Image, and I’ll use the background color instead
background(Color.Cyan)
Copy the code
The complete code
@Composable
private fun TransformGestures(a) {
var angle by remember { mutableStateOf(0f)}var zoom by remember { mutableStateOf(1f)}var offsetX by remember { mutableStateOf(0f)}var offsetY by remember { mutableStateOf(0f) }
Box(
Modifier
.offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
.graphicsLayer(
scaleX = zoom,
scaleY = zoom,
rotationZ = angle
)
.background(Color.Cyan)
.pointerInput(Unit) {
detectTransformGestures(
onGesture = { _, pan, gestureZoom, gestureRotate ->
angle += gestureRotate
zoom *= gestureZoom
offsetX += pan.x
offsetY += pan.y
}
)
}
.fillMaxSize()
)
}
Copy the code