Skip to content

Commit

Permalink
animation fade out when no dragging after 2 sec
Browse files Browse the repository at this point in the history
  • Loading branch information
timhuang1018 committed Oct 10, 2024
1 parent 7ff248d commit 166308f
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 21 deletions.
74 changes: 58 additions & 16 deletions krop-core/src/commonMain/kotlin/io/keeppro/Croppable.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package io.keeppro

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.updateTransition
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.gestures.detectTapGestures
Expand All @@ -20,10 +23,17 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.layout
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
* A croppable and zoomable layout that can handle zoom in and out with drag support, and crop image.
Expand Down Expand Up @@ -51,14 +61,36 @@ fun Croppable(
val settingTranslationY by transition.animateFloat(label = "") { it.translateY }
val scope = rememberCoroutineScope()
val cropWindow: Rect by state.cropWindow
var cropWindowVisible by remember { mutableStateOf(false) }
val windowStateFlow = remember { MutableStateFlow(false) }
var delayJob by remember { mutableStateOf<Job?>(null) }

LaunchedEffect(Unit){
windowStateFlow.collectLatest {
cropWindowVisible = it
if(it){
delayJob?.cancel()
delayJob = scope.launch {
delay(1500)
withContext(Dispatchers.Main){
windowStateFlow.value = false
}
}
}else{
delayJob?.cancel()
delayJob = null
}
}
}



val boxModifier = if (cropHint != null) {
modifier.border(cropHint.borderWidth, cropHint.borderColor).background(cropHint.backgroundColor)
} else {
modifier
}.clipToBounds()
BoxWithConstraints(modifier = boxModifier) {
}
BoxWithConstraints(modifier = boxModifier.clipToBounds()) {
var childWidth by remember { mutableStateOf(0) }
var childHeight by remember { mutableStateOf(0) }

Expand Down Expand Up @@ -127,6 +159,7 @@ fun Croppable(

scope.launch {
state.drag(pan - adjustedOffset)
windowStateFlow.value = true
}
}
}
Expand Down Expand Up @@ -163,20 +196,29 @@ fun Croppable(
) {
content.invoke(this)
}
SudokuGrid(modifier = Modifier.layout { measurable, constraints ->
val placeable = measurable.measure(constraints = constraints.copy(
maxWidth = cropWindow.width.toInt(),
maxHeight = cropWindow.height.toInt(),
minWidth = cropWindow.width.toInt(),
minHeight = cropWindow.height.toInt()
))
layout(
width = cropWindow.width.toInt(),
height = cropWindow.height.toInt()
) {
placeable.place((- cropWindow.topLeft.x.toInt()), (- cropWindow.topLeft.y.toInt()))
}
})

AnimatedVisibility(
visible = cropWindowVisible,
enter = EnterTransition.None,
exit = fadeOut()
){
SudokuGrid(
gridLineColor = cropHint?.gridLineColor ?: Color.Black,
modifier = Modifier.layout { measurable, constraints ->
val placeable = measurable.measure(constraints = constraints.copy(
maxWidth = cropWindow.width.toInt(),
maxHeight = cropWindow.height.toInt(),
minWidth = cropWindow.width.toInt(),
minHeight = cropWindow.height.toInt()
))
layout(
width = cropWindow.width.toInt(),
height = cropWindow.height.toInt()
) {
placeable.place((- cropWindow.topLeft.x.toInt()), (- cropWindow.topLeft.y.toInt()))
}
})
}
}

}
Expand Down
5 changes: 4 additions & 1 deletion krop-core/src/commonMain/kotlin/io/keeppro/CroppableState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -337,16 +337,19 @@ class CroppableState(
}
}

class CropHint(
data class CropHint(
val backgroundColor: Color,
val borderColor: Color,
val borderWidth: Dp,
val gridLineColor: Color?
){

companion object{
val Default = CropHint(
backgroundColor = Color(0xFFBABABA),
borderColor = Color(0xFFBABABA),
borderWidth = 2.dp,
gridLineColor = Color.Black,
)
}
}
6 changes: 3 additions & 3 deletions krop-core/src/commonMain/kotlin/io/keeppro/SudokuGrid.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

@Composable
fun BoxScope.SudokuGrid(modifier: Modifier = Modifier) {
fun BoxScope.SudokuGrid(gridLineColor: Color, modifier: Modifier = Modifier) {
Canvas(modifier = modifier) {
val gridSize = 3 // For a 3x3 grid
val lineThickness = 2.dp.toPx()
Expand All @@ -22,14 +22,14 @@ fun BoxScope.SudokuGrid(modifier: Modifier = Modifier) {
val y = i * cellSizeY
if (i < gridSize) {
drawLine(
color = Color.Black,
color = gridLineColor,
start = Offset(x, 0f),
end = Offset(x, size.height),
strokeWidth = lineThickness
)
}
drawLine(
color = Color.Black,
color = gridLineColor,
start = Offset(0f, y),
end = Offset(size.width, y),
strokeWidth = lineThickness
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.layout
import androidx.compose.ui.unit.dp
Expand Down Expand Up @@ -101,7 +102,7 @@ fun CroppableSample(croppableState: CroppableState, aspectRatio: Float) {
Croppable(
state = croppableState,
contentScale = ContentScale.Crop,
cropHint = CropHint.Default,
cropHint = CropHint.Default.copy(gridLineColor = Color.White.copy(alpha = 0.3f)),
modifier = Modifier
.layout { measurable, constraints ->
val newConstraints = if (aspectRatio >= 1f){
Expand Down

0 comments on commit 166308f

Please sign in to comment.