@@ -10,14 +10,14 @@ import com.smarttoolfactory.cropper.TouchRegion
10
10
import com.smarttoolfactory.cropper.model.AspectRatio
11
11
import com.smarttoolfactory.cropper.settings.CropProperties
12
12
import kotlinx.coroutines.coroutineScope
13
+ import kotlin.math.roundToInt
13
14
14
15
/* *
15
16
* State for cropper with dynamic overlay. Overlay of this state can be moved or resized
16
17
* using handles or touching inner position of overlay. When overlay overflow out of image bounds
17
18
* or moves out of bounds it animates back to valid size and position
18
19
*
19
20
* @param handleSize size of the handle to control, move or scale dynamic overlay
20
- * @param minOverlaySize minimum overlay size that can be shrunk to by moving handles
21
21
* @param imageSize size of the **Bitmap**
22
22
* @param containerSize size of the Composable that draws **Bitmap**
23
23
* @param maxZoom maximum zoom value
@@ -29,11 +29,11 @@ import kotlinx.coroutines.coroutineScope
29
29
* @param rotatable when set to true rotation is enabled
30
30
* @param limitPan limits pan to bounds of parent Composable. Using this flag prevents creating
31
31
* @param fixedAspectRatio when set to true aspect ratio of overlay is fixed
32
+ * @param minDimension minimum size of the overlay, if null defaults to handleSize * 2
32
33
* empty space on sides or edges of parent
33
34
*/
34
35
class DynamicCropState internal constructor(
35
36
private var handleSize : Float ,
36
- private var minOverlaySize : Float ,
37
37
imageSize : IntSize ,
38
38
containerSize : IntSize ,
39
39
drawAreaSize : IntSize ,
@@ -46,6 +46,7 @@ class DynamicCropState internal constructor(
46
46
rotatable : Boolean ,
47
47
limitPan : Boolean ,
48
48
private val fixedAspectRatio : Boolean ,
49
+ private val minDimension : IntSize ?
49
50
) : CropState(
50
51
imageSize = imageSize,
51
52
containerSize = containerSize,
@@ -87,8 +88,6 @@ class DynamicCropState internal constructor(
87
88
88
89
override suspend fun updateProperties (cropProperties : CropProperties , forceUpdate : Boolean ) {
89
90
handleSize = cropProperties.handleSize
90
- minOverlaySize = handleSize * 2
91
-
92
91
super .updateProperties(cropProperties, forceUpdate)
93
92
}
94
93
@@ -131,12 +130,17 @@ class DynamicCropState internal constructor(
131
130
132
131
val change = changes.first()
133
132
133
+ // Default min dimension is handle size * 2
134
+ val doubleHandleSize = handleSize * 2
135
+ val defaultMinDimension =
136
+ IntSize (doubleHandleSize.roundToInt(), doubleHandleSize.roundToInt())
137
+
134
138
// update overlay rectangle based on where its touched and touch position to corners
135
139
// This function moves and/or scales overlay rectangle
136
140
val newRect = updateOverlayRect(
137
141
distanceToEdgeFromTouch = distanceToEdgeFromTouch,
138
142
touchRegion = touchRegion,
139
- minDimension = minOverlaySize ,
143
+ minDimension = minDimension ? : defaultMinDimension ,
140
144
rectTemp = rectTemp,
141
145
overlayRect = overlayRect,
142
146
change = change,
@@ -359,7 +363,7 @@ class DynamicCropState internal constructor(
359
363
private fun updateOverlayRect (
360
364
distanceToEdgeFromTouch : Offset ,
361
365
touchRegion : TouchRegion ,
362
- minDimension : Float ,
366
+ minDimension : IntSize ,
363
367
rectTemp : Rect ,
364
368
overlayRect : Rect ,
365
369
change : PointerInputChange ,
@@ -380,15 +384,15 @@ class DynamicCropState internal constructor(
380
384
381
385
// Set position of top left while moving with top left handle and
382
386
// limit position to not intersect other handles
383
- val left = screenPositionX.coerceAtMost(rectTemp.right - minDimension)
387
+ val left = screenPositionX.coerceAtMost(rectTemp.right - minDimension.width )
384
388
val top = if (fixedAspectRatio) {
385
389
// If aspect ratio is fixed we need to calculate top position based on
386
390
// left position and aspect ratio
387
391
val width = rectTemp.right - left
388
392
val height = width / aspectRatio
389
393
rectTemp.bottom - height
390
394
} else {
391
- screenPositionY.coerceAtMost(rectTemp.bottom - minDimension)
395
+ screenPositionY.coerceAtMost(rectTemp.bottom - minDimension.height )
392
396
}
393
397
Rect (
394
398
left = left,
@@ -402,15 +406,15 @@ class DynamicCropState internal constructor(
402
406
403
407
// Set position of top left while moving with bottom left handle and
404
408
// limit position to not intersect other handles
405
- val left = screenPositionX.coerceAtMost(rectTemp.right - minDimension)
409
+ val left = screenPositionX.coerceAtMost(rectTemp.right - minDimension.width )
406
410
val bottom = if (fixedAspectRatio) {
407
411
// If aspect ratio is fixed we need to calculate bottom position based on
408
412
// left position and aspect ratio
409
413
val width = rectTemp.right - left
410
414
val height = width / aspectRatio
411
415
rectTemp.top + height
412
416
} else {
413
- screenPositionY.coerceAtLeast(rectTemp.top + minDimension)
417
+ screenPositionY.coerceAtLeast(rectTemp.top + minDimension.height )
414
418
}
415
419
Rect (
416
420
left = left,
@@ -424,15 +428,15 @@ class DynamicCropState internal constructor(
424
428
425
429
// Set position of top left while moving with top right handle and
426
430
// limit position to not intersect other handles
427
- val right = screenPositionX.coerceAtLeast(rectTemp.left + minDimension)
431
+ val right = screenPositionX.coerceAtLeast(rectTemp.left + minDimension.width )
428
432
val top = if (fixedAspectRatio) {
429
433
// If aspect ratio is fixed we need to calculate top position based on
430
434
// right position and aspect ratio
431
435
val width = right - rectTemp.left
432
436
val height = width / aspectRatio
433
437
rectTemp.bottom - height
434
438
} else {
435
- screenPositionY.coerceAtMost(rectTemp.bottom - minDimension)
439
+ screenPositionY.coerceAtMost(rectTemp.bottom - minDimension.height )
436
440
}
437
441
438
442
Rect (
@@ -448,15 +452,15 @@ class DynamicCropState internal constructor(
448
452
449
453
// Set position of top left while moving with bottom right handle and
450
454
// limit position to not intersect other handles
451
- val right = screenPositionX.coerceAtLeast(rectTemp.left + minDimension)
455
+ val right = screenPositionX.coerceAtLeast(rectTemp.left + minDimension.width )
452
456
val bottom = if (fixedAspectRatio) {
453
457
// If aspect ratio is fixed we need to calculate bottom position based on
454
458
// right position and aspect ratio
455
459
val width = right - rectTemp.left
456
460
val height = width / aspectRatio
457
461
rectTemp.top + height
458
462
} else {
459
- screenPositionY.coerceAtLeast(rectTemp.top + minDimension)
463
+ screenPositionY.coerceAtLeast(rectTemp.top + minDimension.height )
460
464
}
461
465
462
466
Rect (
0 commit comments