Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Jetpack Compose drag gesture and pinch gesture
Search
Moyuru Aizawa
April 21, 2023
Programming
4.3k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Jetpack Compose drag gesture and pinch gesture
Moyuru Aizawa
April 21, 2023
More Decks by Moyuru Aizawa
See All by Moyuru Aizawa
BLUETOOTH_SCAN and iBeacon
lvla
1
150
graphicsLayer
lvla
0
290
BluetoothDevice.getName()に裏切られた話
lvla
0
410
Jetpack Composeで画像クロップ機能を実装する
lvla
0
1.3k
Jetpack Compose Layout API
lvla
1
710
BLEを使ったアプリを継続的に開発するために
lvla
0
1.1k
RecyclerView.ItemAnimator
lvla
1
380
RecycledViewPool
lvla
1
290
CameraX
lvla
2
2.5k
Other Decks in Programming
See All in Programming
Contextとはなにか
chiroruxx
1
370
スマートグラスで並列バイブコーディング
hyshu
0
260
エンジニア向け会社紹介/Findy Company Profile
findyinc
6
350k
AIで効率化できた業務・日常
ochtum
0
140
Lemonade + Foundry Toolkit でお手軽アプリ開発
seosoft
1
370
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合性を型に閉じ込める
geekplus_tech
0
400
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
360
Javaの型とAI時代に型が大事な理由 / java types and type in AI era
kishida
2
150
Hunting Vulnerabilities in Symfony with LLMs
vinceamstoutz
0
560
生成AI時代にこそ効くGo | Why Go Works in the Age of Generative AI
mom0tomo
8
3.3k
AI 時代のソフトウェア設計の学び方
masuda220
PRO
29
13k
OSもどきOS
arkw
0
590
Featured
See All Featured
The agentic SEO stack - context over prompts
schlessera
0
820
Paper Plane (Part 1)
katiecoart
PRO
0
9.2k
Code Review Best Practice
trishagee
74
20k
Amusing Abliteration
ianozsvald
1
210
Tell your own story through comics
letsgokoyo
1
960
Design in an AI World
tapps
1
250
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
210
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
180
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
210
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
240
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.7k
Rails Girls Zürich Keynote
gr2m
96
14k
Transcript
Jetpack Compose Drag Gesture / Pinch Gesture @MoyuruAizawa
Moyuru Aizawa Software Engineer of Catlog, RABO. Previously at Azit,
CyberAgent, and Eureka. Love Metal, Hardcore and EDM. MoyuruAizawa
github.com/MoyuruAizawa/Cropify
࠷ۙࣄͰ Drag Gestureͱ͔Pinch Gestureͱ͔ ѻͬͨͷͰͦͷհ
CatlogͬͯԿ? Catlog Catlog Board ŮŧŠźƃɺͪΌΜͱ͏Μͨ͜͠?͓ͬͨ͜͠͠? සͩͬͨΓ͠ͳ͍? ମॏͷٸܹͳ૿ݮͱ͔ͯ͠ͳ͍? ͬͯͷ͕͔Δੌ͍IoT൘ ŮŧŠźƃɺӡಈͯ͠Δ?ͪΌΜͱ͝൧৯ͯΔ?Α͘৸ΕͯΔ? ͬͯͷ͕͔Δੌ͍IoTϖϯμϯτ
None
ݩؾείΞମॏτϨϯυɺτΠϨճ ɺ৯ࣄճͳͲ ͋ΒΏΔCatlogσʔλΛγΣΞͯ͠͏ͪ ͷࢠࣗຫͰ͖Δػೳ
‣ ༷ʑͳσʔλΛεςοΧʔԽͯ͠ஔ ‣ υϥοάͯ͠ҠಈͰ͖ΔΑ ‣ ը໘্ΑΓ্ʹυϥοάͨ͠ΒআͰ͖ΔΑ ‣ ϐϯνͨ͠ΒζʔϜͰ͖ΔΑ ‣ CenterVerticallyͱ͔CenterHorizontallyʹεφοϓͰ͖ΔΑ
͜ͷը໘ͷΤϯδχΞత໘നΈ
Ͳ͏Μͷ?
‣ Modifier#pointerInput ‣ PointerInputScope#detectDragGesture ‣ PointerInputScope#detectTransformGesture ॆ࣮ͷgesture API
modifier .pointerInput(Unit) { detectDragGestures { change, dragAmount -> state.offset +=
dragAmount } } .graphicsLayer { translationX = state.offset.x translationY = state.offset.y } PointerInput#detectDragGestures
modifier .pointerInput(Unit) { detectTransformGestures { centroid, pan, zoom, rotation ->
state.scale *= zoom } } .graphicsLayer { scaleX = state.scale scaleY = state.scale } PointerInput#detectTransformGestures
‣ PointerInputScope#detectDragGesture ‣ Drag͚͖͍ͩͨ͞ͳΒ͍ͭ͜Λ͑OK ‣ PointerInputScope#detectTransformGesture ‣ DragҎ֎ʹZoomRotationѻ͍͍ͨͳΒ͜Ε ‣ ֤δΣενϟʔͷ͕ಉ࣌ʹ͘ΔͷͰͲͷδΣενϟʔ͕ܧଓதͳ
ͷ͔ผ͍͠ ‣ Zoom͠ͳ͕ΒDragͱ͔Ͱ͖ͪΌ͏ ‣ onGestureStart, onGestureEndίʔϧόοΫແ͍ APIੇධ
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
‣ Catlogͷཁ݅తʹdetect͔ؔΒॻ͍ͨ ‣ ը໘֎ͷυϥοάෆՄ ‣ εςοΧʔ͔Βը໘·ͰͷڑΛܭࢉɺͦΕΛ͑Δ dragAmountΔ ‣ υϥοάதʹCenterVertically |
CenterHorizontallyۙʹ͖ͨΒͦ ͜εφοϓ ‣ ը໘ͱεφοϓΛߟྀͯ͠࠷ऴతͳdragAmountΛܾఆ͢Δ ‣ ը໘ͰZoomͨ͠Βը໘֎ʹΈग़ͪΌ͍·͢ΑͶ ‣ Ͱ͔͘ͳͬͯը໘֎ʹग़ͯ͠·ͬͨը໘ͣΒͯ͋͛͠Δ ͩΔ͔ͬͨࣄ
δΣενϟʔ࣮͢Δ͚ͩͳΒ؆୯ ΞϓϦͷཁ݅ʹΑͬͯͪΐͬͱμϧ͍
Thank you