Compose Charts
repository·master·Indexed 21 days ago
https://github.com/ehsannarmani/composechartsA Kotlin Multiplatform library for creating charts in Jetpack Compose, supporting Android, Desktop, iOS, and WasmJS. It provides components like ColumnChart, RowChart, and LineChart with extensive customization options for animations, axis properties, bar and dot styling, grid lines, indicators, labels, and interactive popups.
What's inside Compose Charts
- Compose Charts is an animated and flexible multiplatform library designed for Jetpack Compose. It provides practical charting capabilities across multiple platforms including Android, Desktop, iOS, and WasmJS. It is built using Kotlin 2.0.0 and is licensed under the Apache License 2.0.
Use LabelMode.OnPie for Pie Chart Labeling
masterThe
LabelMode.OnPie()mode allows you to display labels directly on or around the pie slices. It supports two types of labels:- Outer Label: Displays the slice's
labeloutside the slice, connected by a guide line. - Inner Label: Displays content inside the slice (defaults to the slice percentage).
Configuration Options for LabelMode.OnPie()
Parameter Description Default outerLineSizeLength of the guide line (radial segment to horizontal segment). 12.dp to 16.dpouterLineStyleAppearance of the guide line (width, stroke style, etc.). Stroke(width = 1.5.dp)innerLabelStyleText style for the inner label. White, 12.sp, Bold showCallback to determine if a slice should show labels. { true }innerLabelContentControls the content inside the slice. PieInnerLabelContent.Percentage()animationSpecAnimation used when labels appear. tween(300, delayMillis = 100)Customizing Inner Label Content
Use
PieInnerLabelContentto change what is displayed inside the slice:PieInnerLabelContent.Custom { pie -> ... }: Provide a custom string based on thePieobject.PieInnerLabelContent.Percentage { percentage -> ... }: Provide a custom string based on the calculated percentage.
// Custom text content labelMode = LabelMode.OnPie( innerLabelContent = PieInnerLabelContent.Custom { pie -> "Hello ${pie.id}" } ) // Custom percentage formatting labelMode = LabelMode.OnPie( innerLabelContent = PieInnerLabelContent.Percentage { percentage -> "${percentage} of total" } )- Outer Label: Displays the slice's
How IndicatorCount works: CountBased vs StepBased
masterThe
countproperty accepts anIndicatorCounttype, which determines how the indicator values are calculated between the chart's minimum and maximum values:CountBased: Divides the range to ensure exactly the requested number of indicators are shown.StepBased: Uses astepByvalue to split the range. It starts from the maximum value and subtracts the step until it reaches the minimum value (e.g., if max is 20, min is -10, and step is 5, indicators will be20, 15, 10, 5, 0, -5, -10).
// CountBased example count = IndicatorCount.CountBased(count = 5) // StepBased example (conceptual) // count = IndicatorCount.StepBased(stepBy = 5.0)Configure animation modes for Row, Column, and Line charts
masterYou can control how animations are executed in
RowChart,ColumnChart, andLineChartusing theanimationModeparameter. This allows you to decide whether animations happen sequentially, simultaneously, or not at all.Available modes:
AnimationMode.OneByOne: Animations run sequentially. For example, in aLineChart, each line will finish its drawing animation before the next one begins.AnimationMode.Together: Animations run asynchronously. You can provide adelayBuilderto stagger the start of each animation relative to the previous one.AnimationMode.None: Disables all animations.
// Sequential animations LineChart( ..., animationMode = AnimationMode.OneByOne ) // Staggered animations (each starts 200ms after the previous one) LineChart( ..., animationMode = AnimationMode.Together(delayBuilder = { index -> index * 200 }) )Handle negative values in ColumnChart
masterThe
ColumnChartsupports negative values. You can explicitly define the scale of the chart usingmaxValueandminValueparameters.Default Behavior:
maxValue: Defaults to the highest value in the provided data.minValue:- If all values are $\ge 0$,
minValuedefaults to0. - If there are values $< 0$,
minValuedefaults to-maxValue.
- If all values are $\ge 0$,
ColumnChart( data = remember { listOf( Bars( label = "1", values = listOf( Bars.Data(value = -40.0, color = Color.Blue) ) ), Bars( label = "2", values = listOf( Bars.Data(value = 50.0, color = Color.Blue) ) ) ) }, maxValue = 75.0, minValue = -75.0 )Install Compose Charts via Gradle
masterTo use Compose Charts in your Android or Kotlin project, add the library as a dependency in your
build.gradle(orbuild.gradle.kts) file using the Maven Central coordinates. Replacelatest_versionwith the current version of the library.dependencies { implementation ("io.github.ehsannarmani:compose-charts:latest_version") }Show Pie Chart Labels Conditionally
masterUse the
showparameter withinLabelMode.OnPie()to control label visibility. This is useful for hiding labels on small slices or only showing labels for selected items to maintain readability.PieChart( ..., labelMode = LabelMode.OnPie( show = { pie -> pie.id == selectedPie?.id } ) )PieChart( ..., labelMode = LabelMode.OnPie( show = { pie -> pie.id == selectedPie?.id } ) )Implement a basic LineChart
masterUse the
LineChartcomposable to render one or more lines. Each line is defined by aLineobject containing alabel, a list ofvalues, and styling options likecoloranddrawStyle. You can control the animation of the lines usinganimationMode.LineChart( modifier = Modifier.fillMaxSize().padding(horizontal = 22.dp), data = remember { listOf( Line( label = "Windows", values = listOf(28.0, 41.0, 5.0, 10.0, 35.0), color = SolidColor(Color(0xFF23af92)), firstGradientFillColor = Color(0xFF2BC0A1).copy(alpha = .5f), secondGradientFillColor = Color.Transparent, strokeAnimationSpec = tween(2000, easing = EaseInOutCubic), gradientAnimationDelay = 1000, drawStyle = DrawStyle.Stroke(width = 2.dp), ) ) }, animationMode = AnimationMode.Together(delayBuilder = { it * 500L }), )Stagger animations using AnimationMode.Together
masterTo create a staggered animation effect where each element starts its animation after a specific delay relative to the previous element, use
AnimationMode.Togetherwith adelayBuilder. ThedelayBuilderis a lambda that receives the currentindexof the animation and returns a delay in milliseconds.For example,
delayBuilder = { index -> index * 200 }will cause the first animation to start at 0ms, the second at 200ms, the third at 400ms, and so on.LineChart( ..., animationMode = AnimationMode.Together(delayBuilder = { index -> index * 200 }) )Access Compose Charts documentation
masterFor a full guide, detailed API references, and comprehensive documentation, visit the official Compose Charts documentation website.
https://ehsannarmani.github.io/ComposeCharts/Customize Line Chart Popups individually
masterIn line charts, you can apply specificPopupPropertiesto each individual line. This is useful if you want to enable popups for some lines while disabling them for others.Implement a Pie Chart
masterUse the
PieChartcomponent to render a pie chart. You provide a list ofPiedata objects, which include alabel,datavalue,color, andselectedColor. You can handle user interaction via theonPieClickcallback to manage selection states.var data by remember { mutableStateOf( listOf( Pie(label = "Android", data = 20.0, color = Color.Red, selectedColor = Color.Green), Pie(label = "Windows", data = 45.0, color = Color.Cyan, selectedColor = Color.Blue), Pie(label = "Linux", data = 35.0, color = Color.Gray, selectedColor = Color.Yellow), ) ) } PieChart( modifier = Modifier.size(200.dp), data = data, onPieClick = { val pieIndex = data.indexOf(it) data = data.mapIndexed { mapIndex, pie -> pie.copy(selected = pieIndex == mapIndex) } }, selectedScale = 1.2f, style = Pie.Style.Fill )var data by remember { mutableStateOf( listOf( Pie(label = "Android", data = 20.0, color = Color.Red, selectedColor = Color.Green), Pie(label = "Windows", data = 45.0, color = Color.Cyan, selectedColor = Color.Blue), Pie(label = "Linux", data = 35.0, color = Color.Gray, selectedColor = Color.Yellow), ) ) } PieChart( modifier = Modifier.size(200.dp), data = data, onPieClick = { println("${it.label} Clicked") val pieIndex = data.indexOf(it) data = data.mapIndexed { mapIndex, pie -> pie.copy(selected = pieIndex == mapIndex) } }, selectedScale = 1.2f, scaleAnimEnterSpec = spring<Float>( dampingRatio = Spring.DampingRatioMediumBouncy, stiffness = Spring.StiffnessLow ), colorAnimEnterSpec = tween(300), colorAnimExitSpec = tween(300), scaleAnimExitSpec = tween(300), spaceDegreeAnimExitSpec = tween(300), style = Pie.Style.Fill )