Skip to content

Commit bb75d4e

Browse files
add gesture and gesture end for DynamicCropState
1 parent e115120 commit bb75d4e

File tree

1 file changed

+84
-48
lines changed

1 file changed

+84
-48
lines changed

cropper/src/main/java/com/smarttoolfactory/cropper/state/DynamicCropState.kt

Lines changed: 84 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -116,20 +116,23 @@ class DynamicCropState internal constructor(
116116
}
117117

118118
override suspend fun onUp(change: PointerInputChange) = coroutineScope {
119-
touchRegion = TouchRegion.None
120119

121-
// Update overlay if it's out of Container bounds
122-
rectTemp = moveOverlayRectToBounds(rectBounds, overlayRect)
123-
animateOverlayRectTo(rectTemp)
120+
if (touchRegion != TouchRegion.None) {
121+
// Update overlay if it's out of Container bounds
122+
rectTemp = moveOverlayRectToBounds(rectBounds, overlayRect)
123+
animateOverlayRectTo(rectTemp)
124124

125-
// Update and animate pan, zoom and image draw area after overlay position is updated
126-
animateTransformationToOverlayBounds()
125+
// Update and animate pan, zoom and image draw area after overlay position is updated
126+
animateTransformationToOverlayBounds()
127+
128+
// Update image draw area after animating pan, zoom or rotation is completed
129+
updateImageDrawRectFromTransformation()
130+
131+
touchRegion = TouchRegion.None
132+
}
127133

128-
// Update image draw area after animating pan, zoom or rotation is completed
129-
updateImageDrawRectFromTransformation()
130134
}
131135

132-
// TODO Write gestures for dynamic crop state
133136
override suspend fun onGesture(
134137
centroid: Offset,
135138
panChange: Offset,
@@ -138,19 +141,70 @@ class DynamicCropState internal constructor(
138141
mainPointer: PointerInputChange,
139142
changes: List<PointerInputChange>
140143
) {
141-
// if (touchRegion == TouchRegion.None) {
142-
// updateTransformState(
143-
// centroid = centroid,
144-
// zoomChange = zoomChange,
145-
// panChange = panChange,
146-
// rotationChange = 0f
147-
// )
144+
if (touchRegion == TouchRegion.None) {
145+
doubleTapped = false
146+
147+
updateTransformState(
148+
centroid = centroid,
149+
zoomChange = zoomChange,
150+
panChange = panChange,
151+
rotationChange = rotationChange
152+
)
153+
154+
// Update image draw rectangle based on pan, zoom or rotation change
155+
updateImageDrawRectFromTransformation()
156+
157+
// Fling Gesture
158+
if (fling) {
159+
if (changes.size == 1) {
160+
addPosition(mainPointer.uptimeMillis, mainPointer.position)
161+
}
162+
}
163+
}
164+
}
165+
166+
override suspend fun onGestureStart() = Unit
167+
168+
override suspend fun onGestureEnd(onBoundsCalculated: () -> Unit) {
169+
// Gesture end might be called after second tap and we don't want to fling
170+
// or animate back to valid bounds when doubled tapped
171+
if (!doubleTapped) {
172+
173+
if (fling && zoom > 1) {
174+
fling {
175+
// We get target value on start instead of updating bounds after
176+
// gesture has finished
177+
updateImageDrawRectFromTransformation()
178+
onBoundsCalculated()
179+
}
180+
} else {
181+
onBoundsCalculated()
182+
}
183+
184+
animateTransformationToOverlayBounds()
185+
}
186+
}
187+
188+
// TODO Write double tap for dynamic crop state
189+
override suspend fun onDoubleTap(
190+
pan: Offset,
191+
zoom: Float,
192+
rotation: Float,
193+
onAnimationEnd: () -> Unit
194+
) {
195+
// doubleTapped = true
196+
//
197+
// if (fling) {
198+
// resetTracking()
148199
// }
200+
// resetWithAnimation(pan = pan, zoom = zoom, rotation = rotation)
201+
// onAnimationEnd()
149202
}
150203

151-
// TODO This function changes translation of image are when zoom is bigger than 1f
152-
// private fun moveOverlayToBounds() {
153-
// val bounds = getBounds()
204+
205+
// TODO Change pan when zoom is bigger than 1f and touchRegion is inside overlay rect
206+
// private suspend fun moveOverlayToBounds(change: PointerInputChange, newRect:Rect) {
207+
// val bounds = getBounds()
154208
// val positionChange = change.positionChangeIgnoreConsumed()
155209
//
156210
// // When zoom is bigger than 100% and dynamic overlay is not at any edge of
@@ -182,25 +236,6 @@ class DynamicCropState internal constructor(
182236
// }
183237
// }
184238

185-
override suspend fun onGestureStart() = Unit
186-
override suspend fun onGestureEnd(onBoundsCalculated: () -> Unit) = Unit
187-
188-
// TODO Write double tap for dynamic crop state
189-
override suspend fun onDoubleTap(
190-
pan: Offset,
191-
zoom: Float,
192-
rotation: Float,
193-
onAnimationEnd: () -> Unit
194-
) {
195-
// doubleTapped = true
196-
//
197-
// if (fling) {
198-
// resetTracking()
199-
// }
200-
// resetWithAnimation(pan = pan, zoom = zoom, rotation = rotation)
201-
// onAnimationEnd()
202-
}
203-
204239
/**
205240
* When pointer is up calculate valid position and size overlay can be updated to inside
206241
* a virtual rect between `topLeft = (0,0)` to `bottomRight=(containerWidth, containerHeight)`
@@ -334,27 +369,28 @@ class DynamicCropState internal constructor(
334369
}
335370

336371
/**
337-
* get touch region inside this rectangle based on touch position.
372+
* get [TouchRegion] based on touch position on screen relative to [overlayRect].
338373
*/
339374
private fun getTouchRegion(
340375
position: Offset,
341376
rect: Rect,
342377
threshold: Float
343378
): TouchRegion {
344379

345-
return when {
380+
val closedTouchRange = -threshold / 2..threshold
346381

347-
position.x - rect.left in 0.0f..threshold &&
348-
position.y - rect.top in 0.0f..threshold -> TouchRegion.TopLeft
382+
return when {
383+
position.x - rect.left in closedTouchRange &&
384+
position.y - rect.top in closedTouchRange -> TouchRegion.TopLeft
349385

350-
rect.right - position.x in 0f..threshold &&
351-
position.y - rect.top in 0.0f..threshold -> TouchRegion.TopRight
386+
rect.right - position.x in closedTouchRange &&
387+
position.y - rect.top in closedTouchRange -> TouchRegion.TopRight
352388

353-
rect.right - position.x in 0f..threshold &&
354-
rect.bottom - position.y in 0.0f..threshold -> TouchRegion.BottomRight
389+
rect.right - position.x in closedTouchRange &&
390+
rect.bottom - position.y in closedTouchRange -> TouchRegion.BottomRight
355391

356-
position.x - rect.left in 0.0f..threshold &&
357-
rect.bottom - position.y in 0.0f..threshold -> TouchRegion.BottomLeft
392+
position.x - rect.left in closedTouchRange &&
393+
rect.bottom - position.y in closedTouchRange -> TouchRegion.BottomLeft
358394

359395

360396
rect.contains(offset = position) -> TouchRegion.Inside

0 commit comments

Comments
 (0)