Skip to content

Commit ea1c69c

Browse files
Update rounded rectangle and ticket path samples
1 parent 33979d7 commit ea1c69c

File tree

2 files changed

+110
-56
lines changed

2 files changed

+110
-56
lines changed
Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.smarttoolfactory.tutorial1_1basics.chapter6_graphics
22

3+
import androidx.compose.ui.geometry.Offset
34
import androidx.compose.ui.geometry.Rect
45
import androidx.compose.ui.geometry.Size
56
import androidx.compose.ui.graphics.Path
@@ -39,133 +40,135 @@ fun createPolygonPath(cx: Float, cy: Float, sides: Int, radius: Float): Path {
3940
}
4041
}
4142

42-
fun roundedRectanglePath(size: Size, cornerRadius: Float): Path {
43+
fun roundedRectanglePath(topLeft: Offset = Offset.Zero, size: Size, cornerRadius: Float): Path {
4344
return Path().apply {
4445
reset()
4546

4647
// Top left arc
4748
val radius = cornerRadius * 2
4849
arcTo(
4950
rect = Rect(
50-
left = 0f,
51-
top = 0f,
52-
right = radius,
53-
bottom = radius
51+
left = topLeft.x,
52+
top = topLeft.y,
53+
right = topLeft.x + radius,
54+
bottom = topLeft.y + radius
5455
),
5556
startAngleDegrees = 180.0f,
5657
sweepAngleDegrees = 90.0f,
5758
forceMoveTo = false
5859
)
5960

60-
lineTo(x = size.width - radius, y = 0f)
61+
lineTo(x = topLeft.x + size.width - radius, y = topLeft.y)
6162

6263
// Top right arc
6364
arcTo(
6465
rect = Rect(
65-
left = size.width - radius,
66-
top = 0f,
67-
right = size.width,
68-
bottom = radius
66+
left = topLeft.x + size.width - radius,
67+
top = topLeft.y,
68+
right = topLeft.x + size.width,
69+
bottom = topLeft.y + radius
6970
),
7071
startAngleDegrees = -90.0f,
7172
sweepAngleDegrees = 90.0f,
7273
forceMoveTo = false
7374
)
7475

75-
lineTo(x = size.width, y = size.height - radius)
76+
lineTo(x = topLeft.x + size.width, y = topLeft.y + size.height - radius)
7677

7778
// Bottom right arc
7879
arcTo(
7980
rect = Rect(
80-
left = size.width - radius,
81-
top = size.height - radius,
82-
right = size.width ,
83-
bottom = size.height
81+
left = topLeft.x + size.width - radius,
82+
top = topLeft.y + size.height - radius,
83+
right = topLeft.x + size.width,
84+
bottom = topLeft.y + size.height
8485
),
8586
startAngleDegrees = 0f,
8687
sweepAngleDegrees = 90.0f,
8788
forceMoveTo = false
8889
)
8990

90-
lineTo(x = radius, y = size.height)
91+
lineTo(x = topLeft.x + radius, y = topLeft.y + size.height)
9192

9293
// Bottom left arc
9394
arcTo(
9495
rect = Rect(
95-
left = 0f,
96-
top = size.height - radius,
97-
right = radius,
98-
bottom = size.height
96+
left = topLeft.x,
97+
top = topLeft.y + size.height - radius,
98+
right = topLeft.x + radius,
99+
bottom = topLeft.y + size.height
99100
),
100101
startAngleDegrees = 90.0f,
101102
sweepAngleDegrees = 90.0f,
102103
forceMoveTo = false
103104
)
104105

105-
lineTo(x = 0f, y = radius)
106+
lineTo(x = topLeft.x, y = topLeft.y + radius)
106107
close()
107108
}
108109
}
109110

110111
/**
112+
* Create a ticket path with given size and corner radius in px with offset [topLeft].
111113
*
112-
*
114+
* Refer [this link](https://juliensalvi.medium.com/custom-shape-with-jetpack-compose-1cb48a991d42)
115+
* for implementation details.
113116
*/
114-
fun ticketPath(size: Size, cornerRadius: Float): Path {
117+
fun ticketPath(topLeft: Offset = Offset.Zero, size: Size, cornerRadius: Float): Path {
115118
return Path().apply {
116119
reset()
117120
// Top left arc
118121
arcTo(
119122
rect = Rect(
120-
left = -cornerRadius,
121-
top = -cornerRadius,
122-
right = cornerRadius,
123-
bottom = cornerRadius
123+
left = topLeft.x + -cornerRadius,
124+
top = topLeft.y + -cornerRadius,
125+
right = topLeft.x + cornerRadius,
126+
bottom = topLeft.y + cornerRadius
124127
),
125128
startAngleDegrees = 90.0f,
126129
sweepAngleDegrees = -90.0f,
127130
forceMoveTo = false
128131
)
129-
lineTo(x = size.width - cornerRadius, y = 0f)
132+
lineTo(x = topLeft.x + size.width - cornerRadius, y = topLeft.y)
130133
// Top right arc
131134
arcTo(
132135
rect = Rect(
133-
left = size.width - cornerRadius,
134-
top = -cornerRadius,
135-
right = size.width + cornerRadius,
136-
bottom = cornerRadius
136+
left = topLeft.x + size.width - cornerRadius,
137+
top = topLeft.y + -cornerRadius,
138+
right = topLeft.x + size.width + cornerRadius,
139+
bottom = topLeft.y + cornerRadius
137140
),
138141
startAngleDegrees = 180.0f,
139142
sweepAngleDegrees = -90.0f,
140143
forceMoveTo = false
141144
)
142-
lineTo(x = size.width, y = size.height - cornerRadius)
145+
lineTo(x = topLeft.x + size.width, y = topLeft.y + size.height - cornerRadius)
143146
// Bottom right arc
144147
arcTo(
145148
rect = Rect(
146-
left = size.width - cornerRadius,
147-
top = size.height - cornerRadius,
148-
right = size.width + cornerRadius,
149-
bottom = size.height + cornerRadius
149+
left = topLeft.x + size.width - cornerRadius,
150+
top = topLeft.y + size.height - cornerRadius,
151+
right = topLeft.x + size.width + cornerRadius,
152+
bottom = topLeft.y + size.height + cornerRadius
150153
),
151154
startAngleDegrees = 270.0f,
152155
sweepAngleDegrees = -90.0f,
153156
forceMoveTo = false
154157
)
155-
lineTo(x = cornerRadius, y = size.height)
158+
lineTo(x = topLeft.x + cornerRadius, y = topLeft.y + size.height)
156159
// Bottom left arc
157160
arcTo(
158161
rect = Rect(
159-
left = -cornerRadius,
160-
top = size.height - cornerRadius,
161-
right = cornerRadius,
162-
bottom = size.height + cornerRadius
162+
left = topLeft.x + -cornerRadius,
163+
top = topLeft.y + size.height - cornerRadius,
164+
right = topLeft.x + cornerRadius,
165+
bottom = topLeft.y + size.height + cornerRadius
163166
),
164167
startAngleDegrees = 0.0f,
165168
sweepAngleDegrees = -90.0f,
166169
forceMoveTo = false
167170
)
168-
lineTo(x = 0f, y = cornerRadius)
171+
lineTo(x = topLeft.x, y = topLeft.y + cornerRadius)
169172
close()
170173
}
171174
}

Tutorial1-1Basics/src/main/java/com/smarttoolfactory/tutorial1_1basics/chapter6_graphics/Tutorial6_1_3CanvasBasics3.kt

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@ import androidx.compose.material.Slider
99
import androidx.compose.material.Text
1010
import androidx.compose.runtime.*
1111
import androidx.compose.ui.Modifier
12-
import androidx.compose.ui.geometry.CornerRadius
13-
import androidx.compose.ui.geometry.Offset
14-
import androidx.compose.ui.geometry.Rect
15-
import androidx.compose.ui.geometry.RoundRect
12+
import androidx.compose.ui.geometry.*
1613
import androidx.compose.ui.graphics.*
1714
import androidx.compose.ui.graphics.drawscope.Stroke
1815
import androidx.compose.ui.platform.LocalConfiguration
@@ -216,25 +213,79 @@ private fun DrawArcToPath() {
216213

217214
@Composable
218215
private fun DrawTicketPathWithArc() {
219-
220216
Canvas(modifier = canvasModifier) {
221-
val path = ticketPath(size, 20.dp.toPx())
222-
drawPath(path, color = Color.Black)
223-
}
224217

225-
}
218+
val canvasWidth = size.width
219+
val canvasHeight = size.height
220+
221+
// Black background
222+
val ticketBackgroundWidth = canvasWidth * .8f
223+
val horizontalSpace = (canvasWidth - ticketBackgroundWidth) / 2
226224

225+
val ticketBackgroundHeight = canvasHeight * .8f
226+
val verticalSpace = (canvasHeight - ticketBackgroundHeight) / 2
227+
228+
// Get ticket path for background
229+
val path1 = ticketPath(
230+
topLeft = Offset(horizontalSpace, verticalSpace),
231+
size = Size(ticketBackgroundWidth, ticketBackgroundHeight),
232+
cornerRadius = 20.dp.toPx()
233+
)
234+
drawPath(path1, color = Color.Black)
235+
236+
// Dashed path in foreground
237+
val ticketForegroundWidth = ticketBackgroundWidth * .95f
238+
val horizontalSpace2 = (canvasWidth - ticketForegroundWidth) / 2
239+
240+
val ticketForegroundHeight = ticketBackgroundHeight * .9f
241+
val verticalSpace2 = (canvasHeight - ticketForegroundHeight) / 2
242+
243+
// Get ticket path for background
244+
val path2 = ticketPath(
245+
topLeft = Offset(horizontalSpace2, verticalSpace2),
246+
size = Size(ticketForegroundWidth, ticketForegroundHeight),
247+
cornerRadius = 20.dp.toPx()
248+
)
249+
drawPath(
250+
path2,
251+
color = Color.Red,
252+
style = Stroke(
253+
width = 2.dp.toPx(),
254+
pathEffect = PathEffect.dashPathEffect(
255+
floatArrayOf(20f, 20f)
256+
)
257+
)
258+
)
259+
}
260+
}
227261

228262
@Composable
229263
private fun DrawRoundedRectangleWithArc() {
230264

231265
Canvas(modifier = canvasModifier) {
232-
val path = roundedRectanglePath(size, 20.dp.toPx())
233-
drawPath(path, color = Color.Red)
234-
235-
}
236266

267+
val path1 = roundedRectanglePath(
268+
topLeft = Offset(100f, 100f),
269+
size = Size(400f, 300f),
270+
cornerRadius = 20.dp.toPx()
271+
)
272+
drawPath(path1, color = Color.Red)
237273

274+
val path2 = roundedRectanglePath(
275+
topLeft = Offset(600f, 200f),
276+
size = Size(200f, 200f),
277+
cornerRadius = 8.dp.toPx()
278+
)
279+
drawPath(
280+
path2, color = Color.Blue,
281+
style = Stroke(
282+
width = 2.dp.toPx(),
283+
pathEffect = PathEffect.dashPathEffect(
284+
floatArrayOf(20f, 20f)
285+
)
286+
)
287+
)
288+
}
238289
}
239290

240291
@Composable

0 commit comments

Comments
 (0)