PanZoomImage with Jetpack Compose

以 Jetpack Compose 實作可移動縮放圖片的 PanZoomImage

John Lu
3 min readDec 11, 2022

Demo App

https://play.google.com/store/apps/details?id=com.nokocreated.kimoji

Kimoji — 用 emoji 記錄你的心情日記

Compose 中的手勢 API

從 high level 到 low level 依序是:

  • Components
    Use bulit-in gesture handling of components
  • Gesture Modifiers
    Add gesture handling and extra functionality
  • Gesture Recognizers
    Detect full gestures inside the pointerInputmodifier
  • Pointer Events
    使用pointerInputmodifier 來處理原始的 pointer events

Gesture Recognizers

  • detectTapGestures
  • detectDragGestures
  • detectVerticalDragGestures
  • detectHorizontalDragGestures
  • detectDragGesturesAfterLongPress
  • detectTransformGestures

detectTapGestures

Modifier.pointerInput(null) {
detectTapGestures(
onDoubleTap = {},
onLongPress = {},
onPress = {},
onTap = {}
)
}

detectDragGestures

Modifier.pointerInput(null) {
detectDragGestures(
onDragStart = {},
onDragCancel = {},
onDragEnd = {},
onDrag = { _, _ -> }
)
}

detectVerticalDragGestures

Modifier.pointerInput(null) {
detectVerticalDragGestures(
onDragStart = {},
onDragCancel = {},
onDragEnd = {},
onVerticalDrag = { _, _ -> }
)
}

detectHorizontalDragGestures

Modifier.pointerInput(null) {
detectHorizontalDragGestures(
onDragStart = {},
onDragCancel = {},
onDragEnd = {},
onHorizontalDrag = { _, _ -> }
)
}

detectDragGesturesAfterLongPress

Modifier.pointerInput(null) {
detectDragGesturesAfterLongPress(
onDragStart = {},
onDragCancel = {},
onDragEnd = {},
onDrag = { _, _ -> }
)
}

detectTransformGestures

Modifier.pointerInput(null) {
detectTransformGestures(
onGesture = { centroid, pan, zoom, rotation -> }
)
}

Gesture Modifiers

  • clickable
  • combinedClickable
  • draggable
  • scrollable
  • transformable

clickable

Modifier.clickable { 

}

combinedClickable

Modifier.combinedClickable(
onClick = {},
onLongClick = {},
onDoubleClick = {}
)

draggable

Modifier.draggable(
orientation = Orientation.Horizontal,
state = rememberDraggableState { delta ->
}
)

scrollable

Modifier.scrollable(
orientation = Orientation.Horizontal,
state = rememberScrollableState { delta ->

}
)

transformable

Modifier.transformable(
state = rememberTransformableState { zoomChange, panChange, rotationChange ->

}
)

Modifier.clickable 源碼

return this
.clickSemantics() // Accessibility
.detectPressAndClickFromKey() // Keyboard support
.indication(interactionSource, indication) // Ripples
.hoverable(enabled = enabled, interactionSource = interactionSource)
.focusableInNonTouchMode(enabled = enabled, interactionSource = interactionSource) // Keyboard support
.then(gestureModifiers)

Hit Testing

Source: Gestures in Jetpack Compose
  • Perform hit testing.
  • The layer passed hit testing will receive touch events continuously.
  • If the upper layer didn’t consume the event, the event is forwarded to the next layer.

PanZoomImage

About Us

CMoney 內部推薦

https://forms.gle/oTAezwSFGmAayQe36

--

--

John Lu
John Lu

Written by John Lu

AI Engineer. Deeply motivated by challenges and tends to be excited by breaking conventional ways of thinking and doing. He builds fun and creative apps.