How to attain UI like this with Jetpack Compose? - android

I've created an Arc with canvas like this:
Canvas(modifier = Modifier.size(255.dp), onDraw = {
rotate(300f) {
drawArc(
color = primary,
startAngle = 0f,
sweepAngle = 180f,
useCenter = false,
style = Stroke(width = 8f)
)
}
})
But, that canvas composable draws in a square shape so that I can't make the edges of arc to touch border of the screen.

Use topLeft = Offset(x, y) in the drawArc function with negative values for x and y if necessary to translate it where you need it.

Related

How do I design an adventure path with curved line in Jetpack Compose?

I want to design an adventure path for educational levels in Jetpack Compose Android, where each level is connected to the next and previous level by a curved line.
Each level is a circular view for example an image that can be clicked.
You can use the Canvas to draw circles and lines.
Something like:
Canvas(modifier = Modifier.fillMaxSize(), onDraw = {
//draw a circle
drawCircle(color = Red,
center = Offset(120f,120f),
radius = 100f)
//draw a simple line.In your case you can use a Bezier curves
val strokePath = Path().apply {
moveTo (220f, 120f)
lineTo (size.width - 220f, 400f)
}
drawPath(
path = strokePath,
color = Blue,
style = Stroke(
width = 3.dp.toPx(),
cap = StrokeCap.Round
)
)
//draw the 2nd circle
drawCircle(color = Color.Red,
center = Offset(size.width - 120f,400f),
radius = 100f)
})
To enable clickable areas you can define a list of Rect for each circle and then apply the pointerInput modifier to the Canvas.
Something like:
val circles = ArrayList<Rect>()
Canvas(modifier = Modifier
.fillMaxSize()
.pointerInput(Unit) {
detectTapGestures(
onTap = { tapOffset ->
circles.add(Rect(top = 70f, left = 70f, bottom = 170f, right = 170f))
circles.add(
Rect(
top = 350f,
left = size.width - 170f,
bottom = 450f,
right = size.width - 70f
)
)
for (rect in circles) {
if (rect.contains(tapOffset)) {
//Handle the click here and do something
//....
}
}
}
)
},
onDraw = { /* .... */ })

Jetpack compose canvas clip to rounded arc shape

I have the following two overlaying 360 degrees arc (essentially two circles) clipped by an arc shape. Unlike drawArc, addArc does not take into style = ... which can be used to define cap = StrokeCap.Round. The current clip looks as expected, an arc clipped with hard edges. Is there a way to round out the corners??
I tried using blendMode, but that does not work as expected since the color of the layers could be diffrent opacity, which blend mode takes in consideration when blending.
Canvas(modifier = Modifier.fillMaxSize()) {
val path = Path().apply {
this.addArc(
oval = Rect(
topLeft = Offset(0F, 0F),
bottomRight = Offset(size.width, size.height)
),
startAngleDegrees = 0F,
sweepAngleDegrees = 240F
)
}
clipPath(path = path) {
// following two drawArc could be replaced w/ drawCircle
drawArc(
color = Color.Magenta.copy(alpha = 0.2F),
startAngle = 0f,
sweepAngle = 360f,
useCenter = false,
style = Stroke(strokeWidthPx2, cap = StrokeCap.Round),
size = Size(size2, size2),
topLeft = Offset(offset2, offset2)
)
drawArc(
color = Color.Cyan,
startAngle = 0f,
sweepAngle = 360f,
useCenter = false,
style = Stroke(strokeWidthPx, cap = StrokeCap.Round),
size = Size(size1, size1),
topLeft = Offset(offset, offset)
)
}
}

Creating arc inside arch with text using jetpack compose

I want to achieve like below, I have tried using the draw arc of compose and able to create one arc but not able to achieve another arch inside it with text at the ends to the arc.
Canvas(
modifier = modifier
) {
drawArc(
color = backgroundColor,
180f,
180f,
false,
style = Stroke(strokeWidth.toPx()),
size = Size(size.width, size.height),
)
drawArc(
color = fillColor,
180f,
percentage * 180f,
false,
style = Stroke(strokeWidth.toPx()),
size = Size(size.width, size.height),
)

How to round only bottom 2 corners with drawRoundRect in Jetpack Compose Canvas

As the title says, I am just trying to figure out how can I round only the bottom 2 corners of the round rect.
drawScope.drawRoundRect(
topLeft = Offset(0f,0f),
size = Size(100f,100f),
cornerRadius = CornerRadius(x = 10f, y = 10f),
color = boxPaint.color
)
This is my current code, which rounds all corners.
Seems like with drawRoundRect you only can setup left or right corner radius.
When you find that the Canvas API is missing something, you can draw almost anything using Path - it has much more flexible API.
val cornerRadius = CornerRadius(10f, 10f)
val path = Path().apply {
addRoundRect(
RoundRect(
rect = Rect(
offset = Offset(0f, 0f),
size = Size(100f, 100f),
),
bottomLeft = cornerRadius,
bottomRight = cornerRadius,
)
)
}
drawPath(path, color = Color.Red)

Arc/Semicircle Shape in Jetpack Compose

I'm looking to draw an arc type shape in Jetpack Compose but I'm really struggling to figure out the best way to do it. When I use drawArc, I can't seem to start the arc from the bottom left corner, it just starts from left middle. I've also tried drawRoundRect but I can't find a way to just round the top left and top right corners.
I'll attach a picture, I don't need the white handle within the shape. Desired result:
drawRoundRect attempt:
drawArc attempt:
You could make it by using a a canvas with your device width but try to increase arc limits beyond device width. With this code
Canvas(modifier = Modifier.fillMaxSize()) {
val canvasWidth = size.width
val canvasHeight = size.height
val formWidth = (canvasWidth * 2)
val xPos = canvasWidth / 2
drawArc(
Color.Black,
0f,
-180f,
useCenter = true,
size = Size(formWidth, 600f),
topLeft = Offset(x = -xPos, y = canvasHeight - 300)
)
}
Arc at bottom looks like this:
more info
You can draw it like this
Placed it to center for demonstration and border is to show that it doesn't overflow Canvas, if you don't pay attention, Canvas draws out of its borders unless use Modifier.clipbounds() is used on Canvas Modifier.
Trick for drawing half arc is to set two times of Canvas height, since arc is drawn inside a rectangle in principle. Changind height of Modifier of canvas changes height of arc.
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Canvas(
modifier = Modifier
.border(2.dp, Color.Red)
.fillMaxWidth()
.height(80.dp),
) {
val canvasWidth = size.width
val canvasHeight = size.height
drawArc(
Color.Blue,
startAngle = 180f,
sweepAngle = 180f,
useCenter = true,
size = Size(canvasWidth, 2 * canvasHeight)
)
val handleWidth = 200f
val handleHeight = 30f
drawRoundRect(
Color.White,
size = Size(handleWidth, handleHeight),
cornerRadius = CornerRadius(5.dp.toPx(), 5.dp.toPx()),
topLeft = Offset((canvasWidth - handleWidth) / 2, (canvasHeight - handleHeight)/2)
)
}
}
Result
You can check this tutorial about Jetpack Compose which covers Canvas operations in detail.

Categories

Resources