Skip to content

Commit

Permalink
overlay min, max 사이즈 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
daeun1012 committed Mar 30, 2023
1 parent 239ade8 commit 660dbd9
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.layout.ContentScale
Expand All @@ -36,7 +37,6 @@ import com.smarttoolfactory.composecropper.ui.theme.ComposeCropperTheme
import com.smarttoolfactory.cropper.ImageCropper
import com.smarttoolfactory.cropper.model.CornerRadiusProperties
import com.smarttoolfactory.cropper.model.OutlineType
import com.smarttoolfactory.cropper.model.RectCropShape
import com.smarttoolfactory.cropper.model.RoundedCornerCropShape
import com.smarttoolfactory.cropper.settings.*
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -70,7 +70,8 @@ fun ImageCropDemo() {
val handleSize = LocalDensity.current.run { 14.dp.toPx() }
val cornerSize = LocalDensity.current.run { 8.dp.toPx() }
val corner = CornerRadiusProperties(radius = cornerSize)
val minOverlaySize = LocalDensity.current.run { 36.dp.toPx() }
val minOverlaySize = LocalDensity.current.run { Size(36.dp.toPx(), 36.dp.toPx()) }
val maxOverlaySize = LocalDensity.current.run { Size(200.dp.toPx(), 100.dp.toPx()) }

var cropProperties by remember {
mutableStateOf(
Expand All @@ -83,6 +84,7 @@ fun ImageCropDemo() {
pannable = false,
zoomable = false,
minOverlaySize = minOverlaySize,
maxOverlaySize = maxOverlaySize,
)
)
}
Expand All @@ -91,7 +93,6 @@ fun ImageCropDemo() {

var selectionPage by remember { mutableStateOf(SelectionPage.Properties) }


val theme by remember {
derivedStateOf {
cropStyle.cropTheme
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.smarttoolfactory.cropper.settings

import androidx.compose.runtime.Immutable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.Dp
Expand Down Expand Up @@ -37,7 +38,8 @@ object CropDefaults {
fling: Boolean = false,
zoomable: Boolean = true,
rotatable: Boolean = false,
minOverlaySize: Float = handleSize * 2,
minOverlaySize: Size = Size(handleSize * 2, handleSize * 2),
maxOverlaySize: Size = Size.Unspecified
): CropProperties {
return CropProperties(
cropType = cropType,
Expand All @@ -52,6 +54,7 @@ object CropDefaults {
zoomable = zoomable,
rotatable = rotatable,
minOverlaySize = minOverlaySize,
maxOverlaySize = maxOverlaySize,
)
}

Expand Down Expand Up @@ -98,7 +101,8 @@ data class CropProperties internal constructor(
val rotatable: Boolean,
val zoomable: Boolean,
val maxZoom: Float,
val minOverlaySize: Float,
val minOverlaySize: Size,
val maxOverlaySize: Size,
)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ fun rememberCropState(
// Properties of crop state
val handleSize = cropProperties.handleSize
val minOverlaySize = cropProperties.minOverlaySize
val maxOverlaySize = cropProperties.maxOverlaySize
val cropType = cropProperties.cropType
val aspectRatio = cropProperties.aspectRatio
val overlayRatio = cropProperties.overlayRatio
Expand All @@ -39,7 +40,6 @@ fun rememberCropState(
val pannable = cropProperties.pannable
val rotatable = cropProperties.rotatable


return remember(*keys) {
when (cropType) {
CropType.Static -> {
Expand All @@ -54,7 +54,9 @@ fun rememberCropState(
zoomable = zoomable,
pannable = pannable,
rotatable = rotatable,
limitPan = false
limitPan = false,
minOverlaySize = minOverlaySize,
maxOverlaySize = maxOverlaySize
)
}
else -> {
Expand All @@ -67,12 +69,13 @@ fun rememberCropState(
overlayRatio = overlayRatio,
maxZoom = maxZoom,
handleSize = handleSize,
minOverlaySize = minOverlaySize,
fling = fling,
zoomable = zoomable,
pannable = pannable,
rotatable = rotatable,
limitPan = true
limitPan = true,
minOverlaySize = minOverlaySize,
maxOverlaySize = maxOverlaySize,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ abstract class CropState internal constructor(
internal var fling: Boolean = true,
internal var aspectRatio: AspectRatio,
internal var overlayRatio: Float,
minOverlaySize: Size,
maxOverlaySize: Size,
zoomable: Boolean = true,
pannable: Boolean = true,
rotatable: Boolean = false,
Expand All @@ -66,7 +68,9 @@ abstract class CropState internal constructor(
zoomable = zoomable,
pannable = pannable,
rotatable = rotatable,
limitPan = limitPan
limitPan = limitPan,
minOverlaySize = minOverlaySize,
maxOverlaySize = maxOverlaySize
) {

private val animatableRectOverlay = Animatable(
Expand Down Expand Up @@ -402,12 +406,11 @@ abstract class CropState internal constructor(
aspectRatio: AspectRatio,
coefficient: Float
): Rect {

if (aspectRatio == AspectRatio.Unspecified) {

// Maximum width and height overlay rectangle can be measured with
val overlayWidthMax = drawAreaWidth.coerceAtMost(containerWidth * coefficient)
val overlayHeightMax = drawAreaHeight.coerceAtMost(containerHeight * coefficient)
val overlayWidthMax = maxOverlaySize.width.coerceAtMost(drawAreaWidth)
val overlayHeightMax = maxOverlaySize.height.coerceAtMost(drawAreaHeight)

val offsetX = (containerWidth - overlayWidthMax) / 2f
val offsetY = (containerHeight - overlayHeightMax) / 2f
Expand All @@ -418,8 +421,8 @@ abstract class CropState internal constructor(
)
}

val overlayWidthMax = containerWidth * coefficient
val overlayHeightMax = containerHeight * coefficient
val overlayWidthMax = maxOverlaySize.width.coerceAtMost(containerWidth * coefficient)
val overlayHeightMax = maxOverlaySize.height.coerceAtMost(containerHeight * coefficient)

val aspectRatioValue = aspectRatio.value

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ import kotlinx.coroutines.coroutineScope
*/
class DynamicCropState internal constructor(
private var handleSize: Float,
private var minOverlaySize: Float,
minOverlaySize: Size,
maxOverlaySize: Size,
imageSize: IntSize,
containerSize: IntSize,
drawAreaSize: IntSize,
Expand All @@ -50,6 +51,8 @@ class DynamicCropState internal constructor(
drawAreaSize = drawAreaSize,
aspectRatio = aspectRatio,
overlayRatio = overlayRatio,
minOverlaySize = minOverlaySize,
maxOverlaySize = maxOverlaySize,
maxZoom = maxZoom,
fling = fling,
zoomable = zoomable,
Expand Down Expand Up @@ -86,6 +89,7 @@ class DynamicCropState internal constructor(
override suspend fun updateProperties(cropProperties: CropProperties, forceUpdate: Boolean) {
handleSize = cropProperties.handleSize
minOverlaySize = cropProperties.minOverlaySize
maxOverlaySize = cropProperties.maxOverlaySize

super.updateProperties(cropProperties, forceUpdate)
}
Expand Down Expand Up @@ -134,7 +138,8 @@ class DynamicCropState internal constructor(
val newRect = updateOverlayRect(
distanceToEdgeFromTouch = distanceToEdgeFromTouch,
touchRegion = touchRegion,
minDimension = minOverlaySize,
minSize = minOverlaySize,
maxSize = maxOverlaySize,
rectTemp = rectTemp,
overlayRect = overlayRect,
change = change
Expand Down Expand Up @@ -348,7 +353,8 @@ class DynamicCropState internal constructor(
private fun updateOverlayRect(
distanceToEdgeFromTouch: Offset,
touchRegion: TouchRegion,
minDimension: Float,
minSize: Size,
maxSize: Size,
rectTemp: Rect,
overlayRect: Rect,
change: PointerInputChange
Expand All @@ -367,8 +373,16 @@ class DynamicCropState internal constructor(

// Set position of top left while moving with top left handle and
// limit position to not intersect other handles
val left = screenPositionX.coerceAtMost(rectTemp.right - minDimension)
val top = screenPositionY.coerceAtMost(rectTemp.bottom - minDimension)
val left = if(maxSize.width < minSize.width) {
screenPositionX.coerceAtMost(rectTemp.right - minSize.width)
} else {
screenPositionX.coerceIn(minimumValue = rectTemp.right - maxSize.width, maximumValue = rectTemp.right - minSize.width)
}
val top = if(maxSize.height < minSize.height) {
screenPositionX.coerceAtMost(rectTemp.bottom - minSize.height)
} else {
screenPositionY.coerceIn(minimumValue = rectTemp.bottom - maxSize.height, maximumValue = rectTemp.bottom - minSize.height)
}
Rect(
left = left,
top = top,
Expand All @@ -381,8 +395,16 @@ class DynamicCropState internal constructor(

// Set position of top left while moving with bottom left handle and
// limit position to not intersect other handles
val left = screenPositionX.coerceAtMost(rectTemp.right - minDimension)
val bottom = screenPositionY.coerceAtLeast(rectTemp.top + minDimension)
val left = if(maxSize.width < minSize.width) {
screenPositionX.coerceAtMost(rectTemp.right - minSize.width)
} else {
screenPositionX.coerceIn(minimumValue = rectTemp.right - maxSize.width, maximumValue = rectTemp.right - minSize.width)
}
val bottom = if(maxSize.height < minSize.height) {
screenPositionY.coerceAtLeast(rectTemp.top + minSize.height)
} else {
screenPositionY.coerceIn(minimumValue = rectTemp.top + minSize.height, maximumValue = rectTemp.top + maxSize.height)
}
Rect(
left = left,
top = rectTemp.top,
Expand All @@ -395,8 +417,16 @@ class DynamicCropState internal constructor(

// Set position of top left while moving with top right handle and
// limit position to not intersect other handles
val right = screenPositionX.coerceAtLeast(rectTemp.left + minDimension)
val top = screenPositionY.coerceAtMost(rectTemp.bottom - minDimension)
val right = if(maxSize.width < minSize.width) {
screenPositionX.coerceAtLeast(rectTemp.left + minSize.width)
} else {
screenPositionX.coerceIn(minimumValue = rectTemp.left + minSize.width, maximumValue = rectTemp.left + maxSize.width)
}
val top = if(maxSize.height < minSize.height) {
screenPositionY.coerceAtMost(rectTemp.bottom - minSize.height)
} else {
screenPositionY.coerceIn(minimumValue = rectTemp.bottom - maxSize.height, maximumValue = rectTemp.bottom - minSize.height)
}

Rect(
left = rectTemp.left,
Expand All @@ -411,8 +441,16 @@ class DynamicCropState internal constructor(

// Set position of top left while moving with bottom right handle and
// limit position to not intersect other handles
val right = screenPositionX.coerceAtLeast(rectTemp.left + minDimension)
val bottom = screenPositionY.coerceAtLeast(rectTemp.top + minDimension)
val right = if(maxSize.width < minSize.width) {
screenPositionX.coerceAtLeast(rectTemp.left + minSize.width)
} else {
screenPositionX.coerceIn(minimumValue = rectTemp.left + minSize.width, maximumValue = rectTemp.left + maxSize.width)
}
val bottom = if(maxSize.height < minSize.height) {
screenPositionY.coerceAtLeast(rectTemp.top + minSize.height)
} else {
screenPositionY.coerceIn(minimumValue = rectTemp.top + minSize.height, maximumValue = rectTemp.top + maxSize.height)
}

Rect(
left = rectTemp.left,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.smarttoolfactory.cropper.state

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.input.pointer.PointerInputChange
import androidx.compose.ui.unit.IntSize
import com.smarttoolfactory.cropper.model.AspectRatio
Expand All @@ -23,6 +24,8 @@ import kotlinx.coroutines.coroutineScope
* empty space on sides or edges of parent
*/
class StaticCropState internal constructor(
minOverlaySize: Size,
maxOverlaySize: Size,
imageSize: IntSize,
containerSize: IntSize,
drawAreaSize: IntSize,
Expand All @@ -40,6 +43,8 @@ class StaticCropState internal constructor(
drawAreaSize = drawAreaSize,
aspectRatio = aspectRatio,
overlayRatio = overlayRatio,
minOverlaySize = minOverlaySize,
maxOverlaySize = maxOverlaySize,
maxZoom = maxZoom,
fling = fling,
zoomable = zoomable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ open class TransformState(
internal val imageSize: IntSize,
val containerSize: IntSize,
val drawAreaSize: IntSize,
internal var minOverlaySize: Size,
internal var maxOverlaySize: Size,
initialZoom: Float = 1f,
initialRotation: Float = 0f,
minZoom: Float = 1f,
Expand Down

0 comments on commit 660dbd9

Please sign in to comment.