@@ -5,45 +5,57 @@ import androidx.compose.runtime.rememberCoroutineScope
55import androidx.compose.ui.Modifier
66import androidx.compose.ui.composed
77import androidx.compose.ui.draw.clipToBounds
8+ import androidx.compose.ui.geometry.Offset
89import androidx.compose.ui.graphics.graphicsLayer
910import androidx.compose.ui.input.pointer.pointerInput
1011import com.smarttoolfactory.gesture.detectTransformGestures
12+ import com.smarttoolfactory.image.util.getNextZoomLevel
1113import com.smarttoolfactory.image.util.update
1214import kotlinx.coroutines.launch
1315
1416/* *
15- * Modifier that zooms in or out of Composable set to. This zoom modifier has option
16- * to move back to bounds with an animation or option to have fling gesture when user removes
17- * from screen while velocity is higher than threshold to have smooth touch effect.
18- *
19- * @param key is used for [Modifier.pointerInput] to restart closure when any keys assigned
20- * change
21- * @param consume flag to prevent other gestures such as scroll, drag or transform to get
22- * @param clip when set to true clips to parent bounds. Anything outside parent bounds is not
23- * drawn
24- * empty space on sides or edges of parent.
25- * [EnhancedZoomData] of this modifier
26- */
17+ * Modifier that zooms in or out of Composable set to. This zoom modifier has option
18+ * to move back to bounds with an animation or option to have fling gesture when user removes
19+ * from screen while velocity is higher than threshold to have smooth touch effect.
20+ *
21+ * @param key is used for [Modifier.pointerInput] to restart closure when any keys assigned
22+ * change
23+ * @param clip when set to true clips to parent bounds. Anything outside parent bounds is not
24+ * drawn
25+ * @param animatedZoomState State of the zoom that contains option to set initial, min, max zoom,
26+ * enabling rotation, pan or zoom
27+ * @param zoomOnDoubleTap lambda that returns current [ZoomLevel] and based on current level
28+ * enables developer to define zoom on double tap gesture
29+ * @param enabled lambda can be used selectively enable or disable pan and intercepting with
30+ * scroll, drag or lists or pagers using current zoom, pan or rotation values
31+ */
2732fun Modifier.animatedZoom (
2833 key : Any? = Unit ,
29- consume : Boolean = true,
3034 clip : Boolean = true,
3135 animatedZoomState : AnimatedZoomState ,
36+ enabled : (Float , Offset , Float ) -> Boolean = DefaultEnabled ,
37+ zoomOnDoubleTap : (ZoomLevel ) -> Float = animatedZoomState.DefaultOnDoubleTap ,
3238) = composed(
3339
3440 factory = {
3541
3642 val coroutineScope = rememberCoroutineScope()
3743
44+ // Current Zoom level
45+ var zoomLevel = ZoomLevel .Min
46+
47+ // Whether panning should be limited to bounds of gesture area or not
3848 val boundPan = animatedZoomState.limitPan && ! animatedZoomState.rotatable
49+
50+ // If we bound to touch area or clip is true Modifier.clipToBounds is used
3951 val clipToBounds = (clip || boundPan)
4052
4153 val transformModifier = Modifier .pointerInput(key) {
4254 // Pass size of this Composable this Modifier is attached for constraining operations
4355 // inside this bounds
4456 animatedZoomState.size = this .size
4557 detectTransformGestures(
46- consume = consume ,
58+ consume = false ,
4759 onGestureEnd = {
4860 coroutineScope.launch {
4961 animatedZoomState.onGestureEnd {
@@ -52,15 +64,24 @@ fun Modifier.animatedZoom(
5264 },
5365 onGesture = { centroid, pan, zoom, rotate, mainPointer, pointerList ->
5466
67+ val currentZoom = animatedZoomState.zoom
68+ val currentPan = animatedZoomState.pan
69+ val currentRotation = animatedZoomState.rotation
70+ val gestureEnabled = enabled(currentZoom, currentPan, currentRotation)
71+
5572 coroutineScope.launch {
5673 animatedZoomState.onGesture(
5774 centroid = centroid,
58- pan = pan,
75+ pan = if (gestureEnabled) pan else Offset . Zero ,
5976 zoom = zoom,
6077 rotation = rotate,
6178 mainPointer = mainPointer,
6279 changes = pointerList
6380 )
81+
82+ if (gestureEnabled) {
83+ mainPointer.consume()
84+ }
6485 }
6586 }
6687 )
@@ -73,7 +94,9 @@ fun Modifier.animatedZoom(
7394 detectTapGestures(
7495 onDoubleTap = {
7596 coroutineScope.launch {
76- animatedZoomState.onDoubleTap {}
97+ val newZoom = zoomOnDoubleTap(zoomLevel)
98+ zoomLevel = getNextZoomLevel(zoomLevel)
99+ animatedZoomState.onDoubleTap(zoom = newZoom) {}
77100 }
78101 }
79102 )
0 commit comments