Skip to content

Commit

Permalink
build a standalone CropHintWindow
Browse files Browse the repository at this point in the history
  • Loading branch information
timhuang1018 committed Oct 10, 2024
1 parent 166308f commit 8f937b1
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 55 deletions.
60 changes: 7 additions & 53 deletions krop-core/src/commonMain/kotlin/io/keeppro/Croppable.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
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 @@ -22,18 +19,12 @@ import androidx.compose.runtime.setValue
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 io.keeppro.widget.CropHintWindow
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 All @@ -60,29 +51,7 @@ fun Croppable(
val settingTranslationX by transition.animateFloat(label = "") { it.translateX }
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) {
Expand Down Expand Up @@ -197,27 +166,12 @@ fun Croppable(
content.invoke(this)
}

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()))
}
})
if (cropHint != null){
CropHintWindow(
cropHint.gridLineColor,
state.cropWindow.value,
windowStateFlow,
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ data class CropHint(
val backgroundColor: Color,
val borderColor: Color,
val borderWidth: Dp,
val gridLineColor: Color?
val gridLineColor: Color
){

companion object{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package io.keeppro.widget

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Color
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

@Composable
fun BoxScope.CropHintWindow(
gridLineColor: Color,
cropWindow: Rect,
windowStateFlow: MutableStateFlow<Boolean>,
) {
var cropWindowVisible by remember { mutableStateOf(false) }
var delayJob by remember { mutableStateOf<Job?>(null) }
val scope = rememberCoroutineScope()

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


AnimatedVisibility(
visible = cropWindowVisible,
enter = EnterTransition.None,
exit = fadeOut()
) {

SudokuGrid(
gridLineColor = gridLineColor,
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())
)
}
})
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.keeppro
package io.keeppro.widget

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.BoxScope
Expand Down

0 comments on commit 8f937b1

Please sign in to comment.