Skip to content

Commit a8318f3

Browse files
add HandleOverlay
1 parent f2a4598 commit a8318f3

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package com.smarttoolfactory.image.transform
2+
3+
import androidx.compose.animation.core.*
4+
import androidx.compose.foundation.Canvas
5+
import androidx.compose.runtime.Composable
6+
import androidx.compose.runtime.getValue
7+
import androidx.compose.ui.Modifier
8+
import androidx.compose.ui.geometry.Offset
9+
import androidx.compose.ui.geometry.Rect
10+
import androidx.compose.ui.graphics.Color
11+
import androidx.compose.ui.graphics.PathEffect
12+
import androidx.compose.ui.graphics.drawscope.Stroke
13+
import androidx.compose.ui.unit.dp
14+
15+
/**
16+
* Overlay that draws border and handles over
17+
*/
18+
@Composable
19+
internal fun HandleOverlay(
20+
modifier: Modifier,
21+
radius: Float,
22+
rectDraw: Rect,
23+
handlePlacement: HandlePlacement = HandlePlacement.Corner
24+
) {
25+
26+
val transition: InfiniteTransition = rememberInfiniteTransition()
27+
28+
// Infinite phase animation for PathEffect
29+
val phase by transition.animateFloat(
30+
initialValue = 0f,
31+
targetValue = 80f,
32+
animationSpec = infiniteRepeatable(
33+
animation = tween(
34+
durationMillis = 500,
35+
easing = LinearEasing
36+
),
37+
repeatMode = RepeatMode.Restart
38+
)
39+
)
40+
41+
val pathEffect = PathEffect.dashPathEffect(
42+
intervals = floatArrayOf(20f, 20f),
43+
phase = phase
44+
)
45+
46+
// This rect what we get after offsetting inside padding area to draw actual composable
47+
val rect = Rect(
48+
topLeft = Offset(
49+
rectDraw.topLeft.x + radius,
50+
rectDraw.topLeft.y + radius
51+
),
52+
bottomRight = Offset(
53+
rectDraw.bottomRight.x - radius,
54+
rectDraw.bottomRight.y - radius
55+
)
56+
)
57+
58+
Canvas(modifier = modifier) {
59+
60+
61+
drawRect(
62+
topLeft = rect.topLeft,
63+
size = rect.size,
64+
color = Color.White,
65+
style = Stroke(
66+
width = 2.dp.toPx()
67+
)
68+
)
69+
drawRect(
70+
topLeft = rect.topLeft,
71+
size = rect.size,
72+
color = Color.Black,
73+
style = Stroke(
74+
width = 2.dp.toPx(),
75+
pathEffect = pathEffect
76+
)
77+
)
78+
79+
if (handlePlacement == HandlePlacement.Corner || handlePlacement == HandlePlacement.Both) {
80+
drawBorderCircle(
81+
radius = radius,
82+
center = rect.topLeft
83+
)
84+
drawBorderCircle(
85+
radius = radius,
86+
center = rect.topRight
87+
)
88+
drawBorderCircle(
89+
radius = radius,
90+
center = rect.bottomLeft
91+
)
92+
drawBorderCircle(
93+
radius = radius,
94+
center = rect.bottomRight
95+
)
96+
}
97+
98+
if (handlePlacement == HandlePlacement.Side || handlePlacement == HandlePlacement.Both) {
99+
drawBorderCircle(
100+
radius = radius,
101+
center = rect.centerLeft
102+
)
103+
drawBorderCircle(
104+
radius = radius,
105+
center = rect.topCenter
106+
)
107+
drawBorderCircle(
108+
radius = radius,
109+
center = rect.centerRight
110+
)
111+
drawBorderCircle(
112+
radius = radius,
113+
center = rect.bottomCenter
114+
)
115+
}
116+
}
117+
}

0 commit comments

Comments
 (0)