Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<activity android:name="info.appdev.chartexample.compose.HorizontalBarComposeActivity" />
<activity android:name="info.appdev.chartexample.compose.HorizontalBarFullComposeActivity" />
<activity android:name="info.appdev.chartexample.compose.MultiLineComposeActivity" />
<activity android:name="info.appdev.chartexample.compose.PieChartComposeActivity" />
<activity android:name="info.appdev.chartexample.HorizontalBarNegativeChartActivity" />
<activity android:name="info.appdev.chartexample.PieChartActivity" />
<activity android:name="info.appdev.chartexample.PieChartRoundedActivity" />
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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())
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -107,6 +110,7 @@ fun PieChart(
pieChart.centerText = centerText
pieChart.rotationAngle = rotationAngle
pieChart.minAngleForSlices = minAngleForSlices
pieChart.setHoleColor(holeColor.toArgb())

// Description
pieChart.description.let { desc ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ fun PieChartExample() {
transparentCircleRadius = 45f,
centerText = "Market Share",
rotationEnabled = true,
holeColor = Color.Transparent,
usePercentValuesEnabled = true,
drawEntryLabelsEnabled = true,
animationDuration = 1500,
Expand Down
Loading