Slide 1

Slide 1 text

Jetpack Compose Drag Gesture / Pinch Gesture @MoyuruAizawa

Slide 2

Slide 2 text

Moyuru Aizawa Software Engineer of Catlog, RABO. Previously at Azit, CyberAgent, and Eureka. Love Metal, Hardcore and EDM. MoyuruAizawa

Slide 3

Slide 3 text

github.com/MoyuruAizawa/Cropify

Slide 4

Slide 4 text

࠷ۙ࢓ࣄͰ Drag Gestureͱ͔Pinch Gestureͱ͔ ѻͬͨͷͰͦͷ঺հ

Slide 5

Slide 5 text

CatlogͬͯԿ? Catlog Catlog Board ŮŧŠźƃɺͪΌΜͱ͏Μͨ͜͠?͓ͬͨ͜͠͠? ස೘ͩͬͨΓ͠ͳ͍? ମॏͷٸܹͳ૿ݮͱ͔ͯ͠ͳ͍? ͬͯͷ͕෼͔Δੌ͍IoT൘ ŮŧŠźƃɺӡಈͯ͠Δ?ͪΌΜͱ͝൧৯΂ͯΔ?Α͘৸ΕͯΔ? ͬͯͷ͕෼͔Δੌ͍IoTϖϯμϯτ

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

ݩؾείΞ΍ମॏτϨϯυɺτΠϨճ ਺ɺ৯ࣄճ਺ͳͲ ͋ΒΏΔCatlogσʔλΛγΣΞͯ͠͏ͪ ͷࢠࣗຫͰ͖Δػೳ

Slide 8

Slide 8 text

‣ ༷ʑͳσʔλΛεςοΧʔԽͯ͠഑ஔ ‣ υϥοάͯ͠ҠಈͰ͖ΔΑ ‣ ը໘্୺ΑΓ্ʹυϥοάͨ͠Β࡟আͰ͖ΔΑ ‣ ϐϯνͨ͠ΒζʔϜͰ͖ΔΑ ‣ CenterVerticallyͱ͔CenterHorizontallyʹεφοϓͰ͖ΔΑ ͜ͷը໘ͷΤϯδχΞత໘നΈ

Slide 9

Slide 9 text

Ͳ͏΍Μͷ?

Slide 10

Slide 10 text

‣ Modifier#pointerInput ‣ PointerInputScope#detectDragGesture ‣ PointerInputScope#detectTransformGesture ॆ࣮ͷgesture API

Slide 11

Slide 11 text

modifier .pointerInput(Unit) { detectDragGestures { change, dragAmount -> state.offset += dragAmount } } .graphicsLayer { translationX = state.offset.x translationY = state.offset.y } PointerInput#detectDragGestures

Slide 12

Slide 12 text

modifier .pointerInput(Unit) { detectTransformGestures { centroid, pan, zoom, rotation -> state.scale *= zoom } } .graphicsLayer { scaleX = state.scale scaleY = state.scale } PointerInput#detectTransformGestures

Slide 13

Slide 13 text

‣ PointerInputScope#detectDragGesture ‣ Drag͚ͩ͞͹͖͍ͨͳΒ͍ͭ͜Λ࢖͑͹OK ‣ PointerInputScope#detectTransformGesture ‣ DragҎ֎ʹZoom΍Rotation΋ѻ͍͍ͨͳΒ͜Ε ‣ ֤δΣενϟʔͷ஋͕ಉ࣌ʹ͘ΔͷͰͲͷδΣενϟʔ͕ܧଓதͳ ͷ͔൑ผ͠೉͍ ‣ Zoom͠ͳ͕ΒDragͱ͔Ͱ͖ͪΌ͏ ‣ onGestureStart, onGestureEndίʔϧόοΫແ͍ APIੇධ

Slide 14

Slide 14 text

suspend fun PointerInputScope.detectTransformGestures( onGestureStart: (GestureType) -> Unit, onGestureEnd: (GestureType) -> Unit, onDrag: (dragAmount: Offset) -> Unit, onZoom: (zoom: Float) -> Unit, ) { forEachGesture { awaitPointerEventScope { awaitFirstDown(requireUnconsumed = false) val gestureType = detectGesture() ?: return@awaitPointerEventScope onGestureStart(gestureType) do { val event = awaitPointerEvent() when (gestureType) { GestureType.DRAG -> { val dragChange = event.calculatePan() if (dragChange != Offset.Zero) onDrag(dragChange) } GestureType.ZOOM -> { val zoomChange = event.calculateZoom() if (zoomChange != 1f) onZoom(zoomChange) } } event.changes.fastForEach { if (it.positionChanged()) it.consume() } } while (event.changes.fastAny { it.pressed }) onGestureEnd(gestureType) } } } private suspend fun AwaitPointerEventScope.detectGesture(): GestureType? { var zoom = 1f var pan = Offset.Zero val touchSlop = viewConfiguration.touchSlop var gestureType: GestureType? = null do { val event = awaitPointerEvent() zoom *= event.calculateZoom() pan += event.calculatePan() val zoomMotion = abs(1 - zoom) * event.calculateCentroidSize(useCurrent = false) val panMotion = pan.getDistance() if (zoomMotion > touchSlop) { gestureType = GestureType.ZOOM break } if (panMotion > touchSlop) { gestureType = GestureType.DRAG break } } while (event.changes.fastAny { it.pressed }) return gestureType } enum class GestureType { DRAG, ZOOM } ΞϓϦͷཁ݅Λຬͨͤͳ͍ͷͰdetectؔ਺Λࣗ෼Ͱॻ͍ͨ ※Ջͳͱ͖ʹݟͯͶ https://bit.ly/composegesture

Slide 15

Slide 15 text

‣ Catlogͷཁ݅తʹdetectؔ਺͔Βॻ͍ͨ ‣ ը໘֎΁ͷυϥοά͸ෆՄ ‣ εςοΧʔ͔Βը໘୺·Ͱͷڑ཭ΛܭࢉɺͦΕΛ௒͑Δ dragAmount͸࡟Δ ‣ υϥοάதʹCenterVertically | CenterHorizontally෇ۙʹ͖ͨΒͦ ͜΁εφοϓ ‣ ը໘୺໰୊ͱεφοϓΛߟྀͯ͠࠷ऴతͳdragAmountΛܾఆ͢Δ ‣ ը໘୺ͰZoomͨ͠Βը໘֎ʹ͸Έग़ͪΌ͍·͢ΑͶ ‣ Ͱ͔͘ͳͬͯը໘֎ʹग़ͯ͠·ͬͨ෼ը໘಺΁ͣΒͯ͋͛͠Δ ͩΔ͔ͬͨࣄ

Slide 16

Slide 16 text

δΣενϟʔ࣮૷͢Δ͚ͩͳΒ௒؆୯ ΞϓϦͷཁ݅ʹΑͬͯ͸ͪΐͬͱμϧ͍

Slide 17

Slide 17 text

Thank you