
In this article, we’ll learn how to create a pie chart using Canvas in Jetpack Compose. Our final output looks like this:

Prerequisites:
Let’s get started.
First, create an empty Compose project and open MainActivity.kt. Create a PieChart() composable and call it from the onCreate() method. We’ll write our code in it.
MainActivity for the Material 3 Jetpack Compose:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Divider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
YourProjectNameTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
PieChart()
}
}
}
}
}
}
@Composable
fun PieChart() {
}
MainActivity for the Material 2 version:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.Divider
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
BlogPostsTheme(darkTheme = false) {
Column(
modifier = Modifier
.fillMaxSize()
.background(color = Color.White),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
PieChart()
}
}
}
}
}
@Composable
fun PieChart() {
}
Our pie chart needs arc values, colors, legend, and size. Let’s add them as parameters.
@Composable
fun PieChart(
values: List<Float> = listOf(15f, 35f, 50f),
colors: List<Color> = listOf(Color(0xFF58BDFF), Color(0xFF125B7F), Color(0xFF092D40)),
legend: List<String> = listOf("Mango", "Banana", "Apple"),
size: Dp = 200.dp
) {
}
Here, the size of values, colors, and legend must be the same. We need to convert the values into equivalent angles.
@Composable
fun PieChart(
values: List<Float> = listOf(15f, 35f, 50f),
colors: List<Color> = listOf(Color(0xFF58BDFF), Color(0xFF125B7F), Color(0xFF092D40)),
legend: List<String> = listOf("Mango", "Banana", "Apple"),
size: Dp = 200.dp
) {
// Sum of all the values
val sumOfValues = values.sum()
// Calculate each proportion value
val proportions = values.map {
it * 100 / sumOfValues
}
// Convert each proportion to angle
val sweepAngles = proportions.map {
it * 360 / 100
}
}
The proportions list contains the percentage of each value. In a circle, 100% is equivalent to 360 degrees. So, to convert each percentage into an angle (degree), we have multiplied it by the ratio of (360/100).
As our sweep angles are ready, let’s add the Canvas and draw the arcs.
@Composable
fun PieChart(
values: List<Float> = listOf(15f, 35f, 50f),
colors: List<Color> = listOf(Color(0xFF58BDFF), Color(0xFF125B7F), Color(0xFF092D40)),
legend: List<String> = listOf("Mango", "Banana", "Apple"),
size: Dp = 200.dp
) {
// Sum of all the values
val sumOfValues = values.sum()
// Calculate each proportion value
val proportions = values.map {
it * 100 / sumOfValues
}
// Convert each proportion to angle
val sweepAngles = proportions.map {
it * 360 / 100
}
Canvas(
modifier = Modifier
.size(size = size)
) {
var startAngle = -90f
for (i in sweepAngles.indices) {
drawArc(
color = colors[i],
startAngle = startAngle,
sweepAngle = sweepAngles[i],
useCenter = true
)
startAngle += sweepAngles[i]
}
}
}
Now, it looks like this:

First, we have set the startAngle = -90f. It represents the 12’0 clock and acts as a starting point. In each iteration, the startAngle is updated to the sum of its previous value and the current sweepAngle.
Next, let’s display the legend. Create a separate composable called DisplayLegend(). We need color and legend values.
@Composable
fun DisplayLegend(color: Color, legend: String) {
}
Each part contains a line and text. We can use Divider() for the line and the Text() method for the text. Put them in a Row layout.
@Composable
fun DisplayLegend(color: Color, legend: String) {
Row(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Divider(
modifier = Modifier.width(16.dp),
thickness = 4.dp,
color = color
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = legend,
color = Color.Black
)
}
}
Call it from the PieChart() method. Our final code looks like this:
@Composable
fun PieChart(
values: List<Float> = listOf(15f, 35f, 50f),
colors: List<Color> = listOf(Color(0xFF58BDFF), Color(0xFF125B7F), Color(0xFF092D40)),
legend: List<String> = listOf("Mango", "Banana", "Apple"),
size: Dp = 200.dp
) {
// Sum of all the values
val sumOfValues = values.sum()
// Calculate each proportion value
val proportions = values.map {
it * 100 / sumOfValues
}
// Convert each proportions to angle
val sweepAngles = proportions.map {
it * 360 / 100
}
Canvas(
modifier = Modifier
.size(size = size)
) {
var startAngle = -90f
for (i in sweepAngles.indices) {
drawArc(
color = colors[i],
startAngle = startAngle,
sweepAngle = sweepAngles[i],
useCenter = true
)
startAngle += sweepAngles[i]
}
}
Spacer(modifier = Modifier.height(32.dp))
Column {
for (i in values.indices) {
DisplayLegend(color = colors[i], legend = legend[i])
}
}
}
@Composable
fun DisplayLegend(color: Color, legend: String) {
Row(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Divider(
modifier = Modifier.width(16.dp),
thickness = 4.dp,
color = color
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = legend,
color = Color.Black
)
}
}
Output:

This is all about the pie chart in Jetpack Compose. I hope you have learned something new. If you have any doubts, leave a comment below.
Related Articles:
References: