Welcome to Custom Shapes
- Jetpack Compose, an open-source project focused on creating beautiful and unique custom shapes in Jetpack Compose. This project aims to provide a collection of custom shape implementations that you can easily integrate into your Compose projects, enabling you to design eye-catching and visually appealing UI elements.
Whether you are a beginner or an experienced Compose developer, this project offers a variety of pre-built shapes that can be utilized to enhance your app's user interface with creative and engaging designs.
You can read the step-by-step guide in my medium story.
Hexagon: Create hexagonal shapes with rounded corners and adjust the size according to your screen's dimensions.
Star: Design star shapes with a customizable number of points and inner radius for various star effects.
Heart: Craft heart shapes with smooth curves and adjusts the height and width as desired.
Ticket: Draw ticket shapes with rounded corners for visually appealing ticket-like elements.
Diamond: Create diamond shapes with straight lines for an elegant and modern appearance.
Android Studio verison used : Android Studio Hedgehog | 2023.1.1 Canary 11
Hexagon | Star | Heart |
---|---|---|
Ticket | Diamond |
---|---|
class HexagonShape : Shape {
override fun createOutline(
size: Size,
layoutDirection: LayoutDirection,
density: Density
): Outline {
return Outline.Generic(
path = drawCustomHexagonPath(size)
)
}
}
private fun drawCustomHexagonPath(size: Size): Path {
return Path().apply {
val radius = min(size.width / 2f, size.height / 2f)
val triangleHeight = (sqrt(3.0) * radius / 2)
val centerX = size.width / 2
val centerY = size.height / 2
moveTo(x = centerX, y = centerY + radius)
lineTo(x = (centerX - triangleHeight).toFloat(), y = centerY + radius / 2)
lineTo(x = (centerX - triangleHeight).toFloat(), y = centerY - radius / 2)
lineTo(x = centerX, y = centerY - radius)
lineTo(x = (centerX + triangleHeight).toFloat(), y = centerY - radius / 2)
lineTo(x = (centerX + triangleHeight).toFloat(), y = centerY + radius / 2)
close()
}
}
class StarShape : Shape {
override fun createOutline(
size: Size,
layoutDirection: LayoutDirection,
density: Density
): Outline {
return Outline.Generic(
path = drawStarPath(size)
)
}
}
private fun drawStarPath(size: Size): Path {
return Path().apply {
val numPoints = 5
val centerX = size.width / 2f
val centerY = size.height / 2f
val outerRadius = min(size.width, size.height) / 2f
val innerRadius = outerRadius / 2.5f // Adjust the inner radius as needed
val doublePi = 2 * PI
val angleIncrement = doublePi / numPoints
var angle = -PI / 2f // Start angle at the top point of the star
moveTo(
x = (centerX + outerRadius * cos(angle)).toFloat(),
y = (centerY + outerRadius * sin(angle)).toFloat()
)
// Draw the points of the star in the correct sequence
for (i in 1..numPoints) {
angle += angleIncrement / 2 // Move to the inner angle first
lineTo(
x = (centerX + innerRadius * cos(angle)).toFloat(),
y = (centerY + innerRadius * sin(angle)).toFloat()
)
angle += angleIncrement / 2 // Move to the outer angle
lineTo(
x = (centerX + outerRadius * cos(angle)).toFloat(),
y = (centerY + outerRadius * sin(angle)).toFloat()
)
}
close()
}
}
class HeartShape : Shape {
override fun createOutline(
size: Size,
layoutDirection: LayoutDirection,
density: Density
): Outline {
return Outline.Generic(
path = drawHeartPath(size)
)
}
}
private fun drawHeartPath(size: Size): Path {
return Path().apply {
val width: Float = size.width
val height: Float = size.height
// Starting point
moveTo(x = width / 2, y = height / 5)
// Upper left path
cubicTo(
x1 = 5 * width / 14, y1 = 0f,
x2 = 0f, y2 = height / 15,
x3 = width / 28, y3 = 2 * height / 5
)
// Lower left path
cubicTo(
x1 = width / 14, y1 = 2 * height / 3,
x2 = 3 * width / 7, y2 = 5 * height / 6,
x3 = width / 2, y3 = height
)
// Lower right path
cubicTo(
x1 = 4 * width / 7, y1 = 5 * height / 6,
x2 = 13 * width / 14, y2 = 2 * height / 3,
x3 = 27 * width / 28, y3 = 2 * height / 5
)
// Upper right path
cubicTo(
x1 = width, y1 = height / 15,
x2 = 9 * width / 14, y2 = 0f,
x3 = width / 2, y3 = height / 5
)
close()
}
}
class TicketShape : Shape {
override fun createOutline(
size: Size,
layoutDirection: LayoutDirection,
density: Density
): Outline {
return Outline.Generic(
path = drawTicketPath(size = size)
)
}
}
private fun drawTicketPath(size: Size): Path {
return Path().apply {
val cornerRadius = 70f
// Top left arc
arcTo(
rect = Rect(
left = -cornerRadius,
top = -cornerRadius,
right = cornerRadius,
bottom = cornerRadius
),
startAngleDegrees = 90.0f,
sweepAngleDegrees = -90.0f,
forceMoveTo = false
)
lineTo(x = size.width - cornerRadius, y = 0f)
// Top right arc
arcTo(
rect = Rect(
left = size.width - cornerRadius,
top = -cornerRadius,
right = size.width + cornerRadius,
bottom = cornerRadius
),
startAngleDegrees = 180.0f,
sweepAngleDegrees = -90.0f,
forceMoveTo = false
)
lineTo(x = size.width, y = size.height - cornerRadius)
// Bottom right arc
arcTo(
rect = Rect(
left = size.width - cornerRadius,
top = size.height - cornerRadius,
right = size.width + cornerRadius,
bottom = size.height + cornerRadius
),
startAngleDegrees = 270.0f,
sweepAngleDegrees = -90.0f,
forceMoveTo = false
)
lineTo(x = cornerRadius, y = size.height)
// Bottom left arc
arcTo(
rect = Rect(
left = -cornerRadius,
top = size.height - cornerRadius,
right = cornerRadius,
bottom = size.height + cornerRadius
),
startAngleDegrees = 0.0f,
sweepAngleDegrees = -90.0f,
forceMoveTo = false
)
lineTo(x = 0f, y = cornerRadius)
close()
}
}
class DiamondShape : Shape {
override fun createOutline(
size: Size,
layoutDirection: LayoutDirection,
density: Density
): Outline {
return Outline.Generic(
path = drawDiamondPath(size)
)
}
}
private fun drawDiamondPath(size: Size): Path {
return Path().apply {
val centerX = size.width / 2f
val diamondCurve = 60f
val width = size.width
val height = size.height
moveTo(x = 0f + diamondCurve, y = 0f)
lineTo(x = width - diamondCurve, y = 0f)
lineTo(x = width, y = diamondCurve)
lineTo(x = centerX, y = height)
lineTo(x = 0f, y = diamondCurve)
close()
}
}
@Composable
fun Hexagon(modifier: Modifier = Modifier) {
Box(
modifier = modifier
.clip(HexagonShape())
.background(md_theme_light_inversePrimary),
contentAlignment = Alignment.Center
) {
// Your content here
}
}
Contributions are what make the open-source community such a fantastic place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you would like to contribute, please follow these steps:
- Open an issue first to discuss what you would like to change.
- Fork the Project
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a pull request
Please make sure to update tests as appropriate.
👤 DawinderGill
Feel free to ping me 😉
Copyright © 2023 - DawinderGill