@@ -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