diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a6acf71d3..473cd9aa6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -28,6 +28,7 @@
+
diff --git a/app/src/main/kotlin/info/appdev/chartexample/compose/PieChartComposeActivity.kt b/app/src/main/kotlin/info/appdev/chartexample/compose/PieChartComposeActivity.kt
new file mode 100644
index 000000000..118af34bd
--- /dev/null
+++ b/app/src/main/kotlin/info/appdev/chartexample/compose/PieChartComposeActivity.kt
@@ -0,0 +1,255 @@
+package info.appdev.chartexample.compose
+
+import android.os.Bundle
+import androidx.activity.compose.setContent
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.MoreVert
+import androidx.compose.material3.DropdownMenu
+import androidx.compose.material3.DropdownMenuItem
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Slider
+import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableFloatStateOf
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.unit.dp
+import info.appdev.chartexample.notimportant.DemoBaseCompose
+import info.appdev.charting.components.Legend
+import info.appdev.charting.compose.PieChart
+import info.appdev.charting.data.PieData
+import info.appdev.charting.data.PieDataSet
+import info.appdev.charting.data.PieEntryFloat
+import timber.log.Timber
+
+class PieChartComposeActivity : DemoBaseCompose() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContent {
+ MaterialTheme {
+ PieChartScreen(onViewGithub = { viewGithub() })
+ }
+ }
+ }
+
+ private val holeColors = listOf(
+ Color.White,
+ Color.LightGray,
+ Color(0xFFB2EBF2),
+ Color.Black,
+ Color.Transparent
+ )
+
+ @OptIn(ExperimentalMaterial3Api::class)
+ @Composable
+ fun PieChartScreen(onViewGithub: () -> Unit) {
+ var showMenu by remember { mutableStateOf(false) }
+ var drawHoleEnabled by remember { mutableStateOf(true) }
+ var usePercentValues by remember { mutableStateOf(true) }
+ var drawEntryLabels by remember { mutableStateOf(true) }
+ var drawRoundedSlices by remember { mutableStateOf(false) }
+ var holeColorIndex by remember { mutableIntStateOf(0) }
+ var animationTrigger by remember { mutableIntStateOf(0) }
+ var holeRadiusValue by remember { mutableFloatStateOf(45f) }
+
+ Scaffold(
+ topBar = {
+ TopAppBar(
+ title = { Text("PieChartCompose") },
+ colors = TopAppBarDefaults.topAppBarColors(
+ containerColor = MaterialTheme.colorScheme.primary,
+ titleContentColor = MaterialTheme.colorScheme.onPrimary
+ ),
+ actions = {
+ Box {
+ IconButton(
+ onClick = { showMenu = true },
+ modifier = Modifier.testTag("menuButton")
+ ) {
+ Icon(
+ Icons.Default.MoreVert,
+ contentDescription = "Menu",
+ tint = MaterialTheme.colorScheme.onPrimary
+ )
+ }
+ DropdownMenu(
+ expanded = showMenu,
+ onDismissRequest = { showMenu = false },
+ modifier = Modifier.testTag("dropdownMenu")
+ ) {
+ DropdownMenuItem(
+ text = { Text("View on GitHub") },
+ onClick = {
+ showMenu = false
+ onViewGithub()
+ },
+ modifier = Modifier.testTag("menuItem_View on GitHub")
+ )
+ DropdownMenuItem(
+ text = { Text("Toggle Hole") },
+ onClick = {
+ showMenu = false
+ drawHoleEnabled = !drawHoleEnabled
+ },
+ modifier = Modifier.testTag("menuItem_Toggle Hole")
+ )
+ DropdownMenuItem(
+ text = { Text("Cycle Hole Color") },
+ onClick = {
+ showMenu = false
+ holeColorIndex = (holeColorIndex + 1) % holeColors.size
+ },
+ modifier = Modifier.testTag("menuItem_Cycle Hole Color")
+ )
+ DropdownMenuItem(
+ text = { Text("Toggle Percent Values") },
+ onClick = {
+ showMenu = false
+ usePercentValues = !usePercentValues
+ },
+ modifier = Modifier.testTag("menuItem_Toggle Percent Values")
+ )
+ DropdownMenuItem(
+ text = { Text("Toggle Entry Labels") },
+ onClick = {
+ showMenu = false
+ drawEntryLabels = !drawEntryLabels
+ },
+ modifier = Modifier.testTag("menuItem_Toggle Entry Labels")
+ )
+ DropdownMenuItem(
+ text = { Text("Toggle Rounded Slices") },
+ onClick = {
+ showMenu = false
+ drawRoundedSlices = !drawRoundedSlices
+ },
+ modifier = Modifier.testTag("menuItem_Toggle Rounded Slices")
+ )
+ DropdownMenuItem(
+ text = { Text("Animate") },
+ onClick = {
+ showMenu = false
+ animationTrigger++
+ },
+ modifier = Modifier.testTag("menuItem_Animate")
+ )
+ }
+ }
+ }
+ )
+ }
+ ) { paddingValues ->
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(paddingValues)
+ .background(Color.White)
+ ) {
+ val pieData = remember { createPieData() }
+
+ PieChart(
+ data = pieData,
+ modifier = Modifier
+ .fillMaxWidth()
+ .weight(1f)
+ .testTag("pieChart"),
+ drawHoleEnabled = drawHoleEnabled,
+ holeRadius = holeRadiusValue,
+ holeColor = holeColors[holeColorIndex],
+ transparentCircleRadius = holeRadiusValue + 5f,
+ centerText = "Market Share",
+ rotationEnabled = true,
+ usePercentValuesEnabled = usePercentValues,
+ drawEntryLabelsEnabled = drawEntryLabels,
+ drawRoundedSlicesEnabled = drawRoundedSlices,
+ animationDuration = if (animationTrigger > 0) 1200 else 0,
+ onValueSelected = { entry, _ ->
+ entry?.let {
+ Timber.d("Selected: ${(it as? PieEntryFloat)?.label} = ${it.y}")
+ }
+ },
+ legend = { legend ->
+ legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM
+ legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER
+ legend.orientation = Legend.LegendOrientation.HORIZONTAL
+ legend.setDrawInside(false)
+ }
+ )
+
+ // Hole radius slider with label
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp, vertical = 8.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Text(
+ text = "Hole:",
+ modifier = Modifier.padding(end = 8.dp),
+ style = MaterialTheme.typography.bodyMedium
+ )
+ Slider(
+ value = holeRadiusValue,
+ onValueChange = { newValue ->
+ holeRadiusValue = newValue
+ },
+ valueRange = 0f..90f,
+ modifier = Modifier.weight(1f)
+ )
+ Text(
+ text = holeRadiusValue.toInt().toString(),
+ modifier = Modifier.padding(start = 8.dp),
+ style = MaterialTheme.typography.bodyMedium
+ )
+ }
+ }
+ }
+ }
+
+ private fun createPieData(): PieData {
+ val entries = listOf(
+ PieEntryFloat(30f, "Product A"),
+ PieEntryFloat(25f, "Product B"),
+ PieEntryFloat(20f, "Product C"),
+ PieEntryFloat(15f, "Product D"),
+ PieEntryFloat(10f, "Product E")
+ )
+
+ val dataSet = PieDataSet(entries.toMutableList(), "Sales Distribution").apply {
+ setColors(
+ mutableListOf(
+ android.graphics.Color.rgb(255, 102, 0),
+ android.graphics.Color.rgb(76, 175, 80),
+ android.graphics.Color.rgb(33, 150, 243),
+ android.graphics.Color.rgb(156, 39, 176),
+ android.graphics.Color.rgb(255, 193, 7)
+ )
+ )
+ valueTextSize = 14f
+ }
+
+ return PieData(dataSet)
+ }
+}
diff --git a/app/src/main/kotlin/info/appdev/chartexample/notimportant/MainActivity.kt b/app/src/main/kotlin/info/appdev/chartexample/notimportant/MainActivity.kt
index 85de01258..8880e7c32 100644
--- a/app/src/main/kotlin/info/appdev/chartexample/notimportant/MainActivity.kt
+++ b/app/src/main/kotlin/info/appdev/chartexample/notimportant/MainActivity.kt
@@ -80,6 +80,7 @@ import info.appdev.chartexample.TimeLineActivity
import info.appdev.chartexample.compose.HorizontalBarComposeActivity
import info.appdev.chartexample.compose.HorizontalBarFullComposeActivity
import info.appdev.chartexample.compose.MultiLineComposeActivity
+import info.appdev.chartexample.compose.PieChartComposeActivity
import info.appdev.chartexample.compose.TimeIntervalComposeActivity
import info.appdev.chartexample.fragments.ViewPagerSimpleChartDemo
import info.appdev.charting.utils.Utils
@@ -225,6 +226,7 @@ class MainActivity : ComponentActivity() {
add(ContentItem("Demonstrate and fix issues"))
add(ContentItem("Gradient", "Show a gradient edge case", GradientActivity::class.java))
add(ContentItem("Timeline", "Show a time line with Unix timestamp", TimeLineActivity::class.java))
+ add(ComposeItem("PieChartCompose", "Render a pie chart in compose, incl. hole color.", PieChartComposeActivity::class.java).toDemoBase())
}
}
}
diff --git a/chartLibCompose/src/main/kotlin/info/appdev/charting/compose/PieChartComposable.kt b/chartLibCompose/src/main/kotlin/info/appdev/charting/compose/PieChartComposable.kt
index bd8957433..2730dd101 100644
--- a/chartLibCompose/src/main/kotlin/info/appdev/charting/compose/PieChartComposable.kt
+++ b/chartLibCompose/src/main/kotlin/info/appdev/charting/compose/PieChartComposable.kt
@@ -5,6 +5,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
@@ -35,6 +36,7 @@ import info.appdev.charting.listener.OnChartValueSelectedListener
* @param usePercentValuesEnabled Whether to use percentage values
* @param drawRoundedSlicesEnabled Whether to draw rounded slices
* @param holeRadius Radius of the center hole (0-100)
+ * @param holeColor Color of the center hole
* @param transparentCircleRadius Radius of the transparent circle (0-100)
* @param centerText Text to display in the center
* @param rotationAngle Starting rotation angle in degrees
@@ -50,7 +52,7 @@ fun PieChart(
onValueSelected: ((EntryFloat?, Highlight?) -> Unit)? = null,
description: String? = null,
legend: ((Legend) -> Unit)? = null,
- backgroundColor: androidx.compose.ui.graphics.Color = androidx.compose.ui.graphics.Color.White,
+ backgroundColor: Color = Color.White,
touchEnabled: Boolean = true,
rotationEnabled: Boolean = true,
highlightPerTapEnabled: Boolean = true,
@@ -60,6 +62,7 @@ fun PieChart(
usePercentValuesEnabled: Boolean = false,
drawRoundedSlicesEnabled: Boolean = false,
holeRadius: Float = 50f,
+ holeColor: Color = Color.White,
transparentCircleRadius: Float = 55f,
centerText: CharSequence = "",
rotationAngle: Float = 270f,
@@ -107,6 +110,7 @@ fun PieChart(
pieChart.centerText = centerText
pieChart.rotationAngle = rotationAngle
pieChart.minAngleForSlices = minAngleForSlices
+ pieChart.setHoleColor(holeColor.toArgb())
// Description
pieChart.description.let { desc ->
diff --git a/chartLibCompose/src/main/kotlin/info/appdev/charting/compose/examples/ChartExamples.kt b/chartLibCompose/src/main/kotlin/info/appdev/charting/compose/examples/ChartExamples.kt
index 7ffb5fbca..7575aece6 100644
--- a/chartLibCompose/src/main/kotlin/info/appdev/charting/compose/examples/ChartExamples.kt
+++ b/chartLibCompose/src/main/kotlin/info/appdev/charting/compose/examples/ChartExamples.kt
@@ -224,6 +224,7 @@ fun PieChartExample() {
transparentCircleRadius = 45f,
centerText = "Market Share",
rotationEnabled = true,
+ holeColor = Color.Transparent,
usePercentValuesEnabled = true,
drawEntryLabelsEnabled = true,
animationDuration = 1500,