codeandtheory / ycharts Goto Github PK
View Code? Open in Web Editor NEWYCharts is a graph library for Android.
License: Apache License 2.0
YCharts is a graph library for Android.
License: Apache License 2.0
When clicking on a bar element, I need the ability to have my own composable display, like a tooltip. A very dated looking X: Y: readout is not something that works in a good design.
Can you at least make the composables editable? I can do it myself but this library is very.... locked down.
I cant imagine very many use cases where "x:x, y:y" is a visually appealing readout.
Also, having the bar color be filled when clicked does not seem to work, yet there is a constructor that seems to allow it. Is this only partially implemented?
Hello, thank you for your hard work on this library! This is exatly what I was looking for.
However, we are using Compose version #1.4.0, and unfortunately it crashes with this version. Most likely it's because of this change "Renamed ModalBottomSheetState, ModalBottomSheetState.Saver and rememberModalBottomSheetState's confirmStateChange to confirmValueChange." See: https://developer.android.com/jetpack/androidx/releases/compose-material#1.4.0-alpha04
Are you planning to make the library compatible with the latest version of Jetpack Compose? Thanks!
The default line chart has a 'staggered' look which is not found in libs like chart.js or SwiftUI charts. I found a nice article on how to do line smoothing without having this staggered appearance at https://medium.com/mobile-app-development-publication/making-graph-plotting-function-in-jetpack-compose-95c80ee6fc7f. I have forked the repo and modified the line chart to use this to generate the cubic points used for line smoothing, and submitting a pull request for the same.
Basic Cubic Bezier
I clone the project and when I run it on my device, app crashed in a few activities. the issue is related to string conversion to float.
As you see below value from Random.nextDouble(1.0, maxRange.toDouble())
is 48.088231731515215 but formating will cause to change point (.) to comma (,). this could be related to device language because we use comma for decimals in Turkish.
val barValue = "%.2f".format(Random.nextDouble(1.0, maxRange.toDouble())).toFloat()
getGroupBarChartData: 48.088231731515215 2023-08-21 00:34:23.560 10199-10199 AndroidRuntime co.yml.ycharts.app D Shutting down VM 2023-08-21 00:34:23.561 10199-10199 AndroidRuntime co.yml.ycharts.app E FATAL EXCEPTION: main Process: co.yml.ycharts.app, PID: 10199 java.lang.NumberFormatException: For input string: "48,09" at jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054) at jdk.internal.math.FloatingDecimal.parseFloat(FloatingDecimal.java:122) at java.lang.Float.parseFloat(Float.java:455) at co.yml.charts.common.utils.DataUtils.getGroupBarChartData(DataUtils.kt:341) at co.yml.ycharts.app.presentation.CombinedLineAndBarChartActivityKt.BarWithLineChart(CombinedLineAndBarChartActivity.kt:104) at co.yml.ycharts.app.presentation.CombinedLineAndBarChartActivity$onCreate$1$1$2$1$1$1$1.invoke(CombinedLineAndBarChartActivity.kt:76) at co.yml.ycharts.app.presentation.CombinedLineAndBarChartActivity$onCreate$1$1$2$1$1$1$1.invoke(CombinedLineAndBarChartActivity.kt:67) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:135)
Adding Color.Transparent to
val donutChartConfig = PieChartConfig(
backgroundColor = Color.Transparent, //transparent color
strokeWidth = 120f,
activeSliceAlpha = .9f,
isAnimationEnable = true,
labelVisible = true,
labelColor = Color.Black,
isEllipsizeEnabled = true,
labelFontSize = 16.sp,
chartPadding = 16,
)
Column(
modifier = Modifier
.fillMaxWidth().padding(horizontal = 12.dp, vertical = 8.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
DonutPieChart(
modifier = Modifier
.fillMaxWidth()
.background(Color.Transparent),
donutChartData,
donutChartConfig
)
Legend(donutChartData.slices, listOfColor)
}
Results in a black background behind the circle instead of a transparent background.
I use the following configuration for the yAxis
:
val yAxisData = AxisData.Builder()
.steps(4)
.backgroundColor(Color.Red)
.labelAndAxisLinePadding(20.dp)
.axisPosition(
pos = Gravity.RIGHT
)
.labelData { i ->
i.toString()
}.build()
But the yAxis is still on the left, see:
Here's the complete code:
val pointsData: List<Point> =
listOf(Point(0f, 40f), Point(1f, 90f), Point(2f, 0f), Point(3f, 60f), Point(4f, 10f))
val xAxisData = AxisData.Builder()
.axisStepSize(100.dp)
.backgroundColor(Color.Blue)
.steps(pointsData.size - 1)
.labelData { i -> i.toString() }
.labelAndAxisLinePadding(15.dp)
.build()
val yAxisData = AxisData.Builder()
.steps(4)
.backgroundColor(Color.Red)
.labelAndAxisLinePadding(20.dp)
.axisPosition(
pos = Gravity.RIGHT
)
.labelData { i ->
i.toString()
}.build()
val lineChartData = LineChartData(
linePlotData = LinePlotData(
lines = listOf(
Line(
dataPoints = pointsData,
LineStyle(),
IntersectionPoint(),
SelectionHighlightPoint(),
ShadowUnderLine(),
SelectionHighlightPopUp()
)
),
),
xAxisData = xAxisData,
yAxisData = yAxisData,
gridLines = GridLines(),
backgroundColor = Color.White
)
LineChart(
modifier = Modifier
.fillMaxWidth()
.height(300.dp),
lineChartData = lineChartData
)
Pie/Donut charts have an optional onSliceClick
lambda for supporting custom actions as a result of a slice being clicked. This issue is an enhancement to provide similar functionality onBarClick
for BarChart
, GroupBarChart
, HorizontalBarChart
, VerticalBarChart
, and StackedBarChart
.
One example use case is to support navigating to another screen based on the bar clicked.
The solution will likely affect BarPlotData
selectionHighlightData
functionality if both features are coded on the same chart, as both rely on the same click action. Comments on how that should be handled are welcome.
Is it possible to have a non-scrollable LineChart? I can't find a configuration to do so.
I want to try displaying a chart with this library in my application project which still uses xml, how do I display it? can using the xml layout adapted to jetpack compose be directly used for this chart layout?
I want to display many bars in my app. The last bar always is cutted off if there are too many bars. The chart scrolls, but the last bar is not fully displayed.
Can somehow help me?
Here is some dummy preview code:
@Preview
@Composable
private fun Preview_VerticalBarChartPreview() {
val barData = (1..11).map { i ->
co.yml.charts.ui.barchart.models.BarData(
point = Point(i.toFloat(), i.toFloat() * 10),
)
}
val barChartData = BarChartData(
chartData = barData,
xAxisData = AxisData.Builder()
.shouldDrawAxisLineTillEnd(true)
.startDrawPadding(24.dp) // ?
.labelData { index -> barData[index].label }
.build(),
backgroundColor = Color.Transparent,
barStyle = BarStyle().copy(
barWidth = 24.dp,
paddingBetweenBars = 12.dp,
))
BarChart(
modifier = Modifier
.height(300.dp),
barChartData = barChartData
)
}
I am passing the list of lines
val data = LineChartData(
linePlotData = LinePlotData(
lines = listOf(
Line(
dataPoints = pointsData,
LineStyle(),
IntersectionPoint(),
SelectionHighlightPoint(),
ShadowUnderLine(),
SelectionHighlightPopUp()
),
Line(
dataPoints = pointsData2,
LineStyle(),
IntersectionPoint(),
SelectionHighlightPoint(),
ShadowUnderLine(),
SelectionHighlightPopUp()
)
)
),
xAxisData = xAxisData,
yAxisData = yAxisData,
gridLines = GridLines()
)
But I am unable see multiple lines on chart, it is showing only first one
I can see that we are picking only first line from the list of lines in LineChart.kt file
val line = linePlotData.lines.first() (code line no: 81)
Hi,
i have some ui-tests. And if run these tests and i want to test my ui with some charts, these tests are failing.
If i temporarily disable the charts, the test runs successfully.
Does ycharts idles some resources?
How can i fix this? Or is this an issue in the fantastic ycharts library?
Hope anyone can help me.
Catched a crash with LineChart, please help me find a reason.
LineChartKt.drawStraightOrCubicLine
java.lang.IllegalStateException - Offset is unspecified
Fatal Exception: java.lang.IllegalStateException: Offset is unspecified at androidx.compose.ui.geometry.Offset.getX-impl(Offset.kt:67) at co.yml.charts.ui.linechart.LineChartKt.drawStraightOrCubicLine(LineChart.kt:358) at co.yml.charts.ui.linechart.LineChartKt$LineChart$2$1$4.invoke(LineChart.kt:188) at co.yml.charts.ui.linechart.LineChartKt$LineChart$2$1$4.invoke(LineChart.kt:107) at co.yml.charts.chartcontainer.container.ScrollableCanvasContainerKt$ScrollableCanvasContainer$4$1$4$1.invoke(ScrollableCanvasContainer.kt:110) at co.yml.charts.chartcontainer.container.ScrollableCanvasContainerKt$ScrollableCanvasContainer$4$1$4$1.invoke(ScrollableCanvasContainer.kt:108) at androidx.compose.ui.draw.DrawBackgroundModifier.draw(DrawModifier.kt:116) at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:105) at androidx.compose.ui.node.LayoutNodeDrawScope.performDraw(LayoutNodeDrawScope.kt:76) at androidx.compose.ui.node.LayoutNodeDrawScope.drawContent(LayoutNodeDrawScope.kt:55) at androidx.compose.foundation.BackgroundNode.draw(Background.kt:159) at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:105) at androidx.compose.ui.node.LayoutNodeDrawScope.draw-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:86) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:365) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.LayoutNodeDrawScope.drawContent(LayoutNodeDrawScope.kt:66) at androidx.compose.material.ripple.AndroidRippleIndicationInstance.drawIndication(Ripple.android.kt:172) at androidx.compose.foundation.IndicationModifier.draw(Indication.kt:183) at androidx.compose.ui.node.BackwardsCompatNode.draw(BackwardsCompatNode.kt:349) at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:105) at androidx.compose.ui.node.LayoutNodeDrawScope.performDraw(LayoutNodeDrawScope.kt:76) at androidx.compose.ui.node.LayoutNodeDrawScope.drawContent(LayoutNodeDrawScope.kt:55) at androidx.compose.foundation.BackgroundNode.draw(Background.kt:159) at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:105) at androidx.compose.ui.node.LayoutNodeDrawScope.draw-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:86) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:365) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutNode.draw$ui_release(LayoutNode.kt:929) at androidx.compose.ui.node.InnerNodeCoordinator.performDraw(InnerNodeCoordinator.kt:174) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.access$drawContainedDrawModifiers(NodeCoordinator.kt:54) at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:384) at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:383) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2303) at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:496) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:256) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133) at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:383) at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:54) at androidx.compose.ui.platform.RenderNodeApi29.record(RenderNodeApi29.android.kt:209) at androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList(RenderNodeLayer.android.kt:304) at androidx.compose.ui.platform.RenderNodeLayer.drawLayer(RenderNodeLayer.android.kt:246) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:349) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.LayoutNodeDrawScope.drawContent(LayoutNodeDrawScope.kt:66) at androidx.compose.material.ripple.AndroidRippleIndicationInstance.drawIndication(Ripple.android.kt:172) at androidx.compose.foundation.IndicationModifier.draw(Indication.kt:183) at androidx.compose.ui.node.BackwardsCompatNode.draw(BackwardsCompatNode.kt:349) at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:105) at androidx.compose.ui.node.LayoutNodeDrawScope.performDraw(LayoutNodeDrawScope.kt:76) at androidx.compose.ui.node.LayoutNodeDrawScope.drawContent(LayoutNodeDrawScope.kt:55) at androidx.compose.foundation.BackgroundNode.draw(Background.kt:159) at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:105) at androidx.compose.ui.node.LayoutNodeDrawScope.draw-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:86) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:365) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutNode.draw$ui_release(LayoutNode.kt:929) at androidx.compose.ui.node.InnerNodeCoordinator.performDraw(InnerNodeCoordinator.kt:174) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.access$drawContainedDrawModifiers(NodeCoordinator.kt:54) at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:384) at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:383) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2303) at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:496) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:256) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133) at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:383) at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:54) at androidx.compose.ui.platform.RenderNodeApi29.record(RenderNodeApi29.android.kt:209) at androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList(RenderNodeLayer.android.kt:304) at androidx.compose.ui.platform.RenderNodeLayer.drawLayer(RenderNodeLayer.android.kt:246) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:349) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.LayoutNodeDrawScope.drawContent(LayoutNodeDrawScope.kt:66) at androidx.compose.foundation.BackgroundNode.draw(Background.kt:159) at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:105) at androidx.compose.ui.node.LayoutNodeDrawScope.performDraw(LayoutNodeDrawScope.kt:76) at androidx.compose.ui.node.LayoutNodeDrawScope.drawContent(LayoutNodeDrawScope.kt:55) at androidx.compose.foundation.BackgroundNode.draw(Background.kt:159) at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:105) at androidx.compose.ui.node.LayoutNodeDrawScope.draw-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:86) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:365) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutNode.draw$ui_release(LayoutNode.kt:929) at androidx.compose.ui.node.InnerNodeCoordinator.performDraw(InnerNodeCoordinator.kt:174) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.access$drawContainedDrawModifiers(NodeCoordinator.kt:54) at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:384) at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:383) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2303) at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:496) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:256) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133) at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:383) at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:54) at androidx.compose.ui.platform.RenderNodeApi29.record(RenderNodeApi29.android.kt:209) at androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList(RenderNodeLayer.android.kt:304) at androidx.compose.ui.platform.RenderNodeLayer.drawLayer(RenderNodeLayer.android.kt:246) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:349) at androidx.compose.ui.node.LayoutNode.draw$ui_release(LayoutNode.kt:929) at androidx.compose.ui.node.InnerNodeCoordinator.performDraw(InnerNodeCoordinator.kt:174) at androidx.compose.ui.node.LayoutNodeDrawScope.drawContent(LayoutNodeDrawScope.kt:66) at androidx.compose.foundation.DrawOverscrollModifier.draw(AndroidOverscroll.kt:81) at androidx.compose.ui.node.BackwardsCompatNode.draw(BackwardsCompatNode.kt:349) at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:105) at androidx.compose.ui.node.LayoutNodeDrawScope.draw-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:86) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:365) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.access$drawContainedDrawModifiers(NodeCoordinator.kt:54) at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:384) at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:383) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2303) at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:496) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:256) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133) at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:383) at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:54) at androidx.compose.ui.platform.RenderNodeApi29.record(RenderNodeApi29.android.kt:209) at androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList(RenderNodeLayer.android.kt:304) at androidx.compose.ui.platform.RenderNodeLayer.drawLayer(RenderNodeLayer.android.kt:246) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:349) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.access$drawContainedDrawModifiers(NodeCoordinator.kt:54) at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:384) at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:383) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2303) at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:496) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:256) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133) at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:383) at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:54) at androidx.compose.ui.platform.RenderNodeApi29.record(RenderNodeApi29.android.kt:209) at androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList(RenderNodeLayer.android.kt:304) at androidx.compose.ui.platform.RenderNodeLayer.drawLayer(RenderNodeLayer.android.kt:246) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:349) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutNode.draw$ui_release(LayoutNode.kt:929) at androidx.compose.ui.node.InnerNodeCoordinator.performDraw(InnerNodeCoordinator.kt:174) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362) at androidx.compose.ui.node.NodeCoordinator.access$drawContainedDrawModifiers(NodeCoordinator.kt:54) at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:384) at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:383) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2303) at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:496) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:256) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133) at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:383) at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:54) at androidx.compose.ui.platform.RenderNodeApi29.record(RenderNodeApi29.android.kt:209) at androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList(RenderNodeLayer.android.kt:304) at androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:1209) at android.view.View.draw(View.java:24409) at android.view.View.updateDisplayListIfDirty(View.java:23267) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4732) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4704) at android.view.View.updateDisplayListIfDirty(View.java:23214) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4732) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4704) at android.view.View.updateDisplayListIfDirty(View.java:23214) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4732) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4704) at android.view.View.updateDisplayListIfDirty(View.java:23214) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4732) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4704) at android.view.View.updateDisplayListIfDirty(View.java:23214) at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:777) at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:783) at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:881) at android.view.ViewRootImpl.draw(ViewRootImpl.java:5647) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:5330) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:4486) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:3116) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:10885) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1301) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1309) at android.view.Choreographer.doCallbacks(Choreographer.java:923) at android.view.Choreographer.doFrame(Choreographer.java:852) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1283) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8762) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Here is my code
`ConstraintLayout(
modifier = Modifier
.padding(top = 0.dp)
.height(300.dp)
.onGloballyPositioned {
chartWidth = with(density) {
it.size.width.toDp()
}
}) {
val (chart, topPrice, bottomPrice, progress) = createRefs()
//initial height set at 0.dp
val priceString = stringResource(id = R.string.price)
// get local density from composable
val xAxisStepSize = (chartWidth.value / ((coin.pointsData.size) - 1)).dp
val xAxisData = AxisData.Builder()
.axisStepSize(xAxisStepSize)
.labelAndAxisLinePadding(0.dp)
.startPadding(0.dp)
.backgroundColor(Color.Transparent)
.shouldDrawAxisLineTillEnd(true)
.axisLineThickness(0.dp)
.axisLineColor(MaterialTheme.colorScheme.secondary)
.indicatorLineWidth(0.dp)
.steps(coin.pointsData.size - 1)
.build()
val steps = coin.pointsData.size - 1
val yAxisData = AxisData.Builder()
.steps(steps)
.axisPosition(Gravity.RIGHT)
.backgroundColor(Color.Transparent)
.shouldDrawAxisLineTillEnd(true)
.axisLineThickness(0.dp)
.axisLineColor(Color.Transparent)
.indicatorLineWidth(0.dp)
.labelAndAxisLinePadding(0.dp)
.axisOffset(0.dp)
.axisLabelColor(MaterialTheme.colorScheme.secondary)
.axisLabelAngle(45f)
.shouldDrawAxisLineTillEnd(false)
.build()
val lineChartData = LineChartData(
containerPaddingEnd = 0.dp,
paddingRight = 0.dp,
bottomPadding = 8.dp,
paddingTop = 28.dp,
backgroundColor = MaterialTheme.colorScheme.surface,
linePlotData = LinePlotData(
lines = if (coin.pointsData.isEmpty()) listOf() else listOf(
Line(
dataPoints = coin.pointsData.map {
Point(it.x, it.y)
},
LineStyle(
lineType = LineType.SmoothCurve(),
color = MaterialTheme.colorScheme.primary,
width = 6f,
alpha = 1f,
),
IntersectionPoint(
color = MaterialTheme.colorScheme.secondary,
radius = 2.dp,
alpha = 0.1f
),
SelectionHighlightPoint(
color = MaterialTheme.colorScheme.tertiary,
alpha = 0.7f
),
ShadowUnderLine(
color = MaterialTheme.colorScheme.secondary,
alpha = 0.1f,
),
SelectionHighlightPopUp(
backgroundColor = MaterialTheme.colorScheme.secondaryContainer,
backgroundCornerRadius = CornerRadius(8f),
paddingBetweenPopUpAndPoint = 16.dp,
labelSize = TextUnit(15f, TextUnitType.Sp),
labelColor = MaterialTheme.colorScheme.onSecondaryContainer,
popUpLabel = { x, y ->
val selectedIndex =
coin.pointsData.indexOfFirst {
it.y == y
}
Timber.d("selectedIndex: $selectedIndex, coin.formattedPointsDataPriceList: ${coin.formattedPointsDataPriceList}")
val formattedPrice =
if (selectedIndex == -1) "$selectedCurrencySymbol$y"
else try {
"$selectedCurrencySymbol${coin.formattedPointsDataPriceList[selectedIndex]}"
} catch (e: Exception) {
"$selectedCurrencySymbol$y"
}
"$priceString: $formattedPrice"
}
),
)
),
),
gridLines = GridLines(
color = MaterialTheme.colorScheme.secondary.copy(alpha = 0.05f),
),
xAxisData = xAxisData,
yAxisData = yAxisData,
isZoomAllowed = false,
)
LineChart(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()
.background(
Color.Transparent,
shape = MaterialTheme.shapes.medium
)
.constrainAs(chart) {
top.linkTo(parent.top)
start.linkTo(parent.start)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
},
lineChartData = lineChartData
)
Text(
text = coin.formattedPriceMin,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.5f),
style = MaterialTheme.typography.bodySmall,
maxLines = 1,
modifier = Modifier
.padding(start = 16.dp, bottom = 8.dp)
.constrainAs(bottomPrice) {
start.linkTo(parent.start)
bottom.linkTo(parent.bottom)
}
)
// max price
Text(
text = coin.formattedPriceMax,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.5f),
style = MaterialTheme.typography.bodySmall,
maxLines = 1,
modifier = Modifier
.padding(start = 16.dp, top = 8.dp)
.constrainAs(topPrice) {
start.linkTo(parent.start)
top.linkTo(parent.top)
}
)
Box(modifier = Modifier
.padding(8.dp)
.size(24.dp)
.constrainAs(
progress
) {
end.linkTo(parent.end)
top.linkTo(parent.top)
}) {
if (isRefreshing) {
InfinitePieChartProgressIndicator(
size = 24.dp,
strokeWidth = 4.dp
)
}
}
}`
How to make CombinedChart non scrollable and add dual x-y-axis with label somewhere around the axis-line.
The library is amazing but, for the line chart, the line points for Y Axis are not accurately plotted. Any solution will be welcomed.
Hello!
Hope you might be able to help - this has suddenly started happening to me, and I'm not sure why. I don't think i've changed any dependencies
java.lang.NullPointerException: Parameter specified as non-null is null: method androidx.compose.material.ModalBottomSheetKt.rememberModalBottomSheetState, parameter confirmStateChange at androidx.compose.material.ModalBottomSheetKt.rememberModalBottomSheetState(Unknown Source:9) at co.yml.charts.ui.linechart.LineChartKt.LineChart(LineChart.kt:59)
Any thoughts gratefully received.
Best Wishes
Pete
Im using my own custom Material 3 Theme which is giving this error when i try to run my app:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mcnut.banking/com.mcnut.banking.fragments.LoginActivity}: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
Manifest File:
android:theme="@style/Theme.Budgeting">
Activity Class:
class LoginActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {...
Themes.xml:
<style name="Theme.Budgeting" parent="Theme.Material3.Dark.NoActionBar">...
Is there any way i can avoid this error coming up or is it just not possible to use the charts in a theme like this.
Thanks
Did I do wrong when setting the chart? All I did is put my data in the chart component, as you can see the data in y value is 1 and the highest is 2 which my data has no 0 value, its 1 and 2s only. Why does it do this, is it my setup fault or is it a bug? Anyone can help me? Thanks
@Composable
private fun getLineChartData(pointData: List<Point>, yScale: Int): LineChartData {
return LineChartData(
linePlotData = LinePlotData(
lines = listOf(
Line(
dataPoints = pointData,
LineStyle(
color = MaterialTheme.colorScheme.onTertiaryContainer,
width = 6f,
lineType = LineType.SmoothCurve(isDotted = false)
),
IntersectionPoint(
color = MaterialTheme.colorScheme.onTertiaryContainer,
radius = 4.dp
),
SelectionHighlightPoint(color = MaterialTheme.colorScheme.onTertiaryContainer),
ShadowUnderLine(
alpha = 0.5f,
brush = Brush.verticalGradient(
colors = listOf(
MaterialTheme.colorScheme.onTertiaryContainer,
Color.Transparent
)
)
),
SelectionHighlightPopUp()
)
)
),
backgroundColor = MaterialTheme.colorScheme.tertiaryContainer,
xAxisData = getXAxisData(pointData = pointData),
yAxisData = getYAxisData(yScale = yScale),
gridLines = GridLines(
color = MaterialTheme.colorScheme.onTertiaryContainer,
enableVerticalLines = false
),
paddingRight = 0.dp
)
}
How to make chart show in RTL instead of LTR ?
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
org.jetbrains.kotlinx:kotlinx-coroutines-core
, org.jetbrains.kotlinx:kotlinx-coroutines-test
, org.jetbrains.kotlinx:kotlinx-coroutines-android
)io.mockk:mockk-android
, org.junit.jupiter:junit-jupiter
, com.android.test
, org.jetbrains.kotlin:kotlin-test-common
)com.android.library
, com.android.application
, com.android.tools.build:gradle
)androidx.core:core-ktx
, androidx.navigation:navigation-testing
, androidx.lifecycle:lifecycle-runtime-ktx
, androidx.lifecycle:lifecycle-viewmodel-ktx
)androidx.compose.ui:ui-test-junit4
, androidx.navigation:navigation-compose
, androidx.lifecycle:lifecycle-viewmodel-compose
, androidx.activity:activity-compose
, androidx.compose:compose-bom
)org.jetbrains.kotlin:kotlin-android-extensions
, org.jetbrains.kotlin.jvm
, org.jetbrains.kotlin.android
, org.jetbrains.kotlin:kotlin-stdlib-common
)org.jlleitschuh.gradle.ktlint
, org.jetbrains.dokka
, org.jetbrains.dokka:dokka-gradle-plugin
, org.sonarqube
).github/workflows/android.yml
actions/checkout v3
actions/setup-java v3
.github/workflows/publish.yml
actions/checkout v3
actions/setup-java v3
gradle.properties
settings.gradle.kts
build.gradle.kts
org.jetbrains.kotlin:kotlin-android-extensions 1.8.20
org.jetbrains.dokka 1.8.10
YChartsLib/build.gradle.kts
app/build.gradle.kts
build-logic/settings.gradle.kts
build-logic/build.gradle.kts
experiments/chartcontainer/build.gradle.kts
experiments/piechartcontainer/build.gradle.kts
gradle/libs.versions.toml
com.android.tools.build:gradle 8.0.2
org.jetbrains.dokka:dokka-gradle-plugin 1.8.10
org.jetbrains.kotlin:kotlin-android-extensions 1.8.20
androidx.activity:activity-compose 1.7.0
androidx.appcompat:appcompat 1.6.1
androidx.compose:compose-bom 2023.05.01
androidx.compose.ui:ui-test-junit4 1.4.3
androidx.core:core-ktx 1.9.0
androidx.navigation:navigation-compose 2.5.3
androidx.lifecycle:lifecycle-viewmodel-compose 2.6.1
androidx.lifecycle:lifecycle-viewmodel-ktx 2.6.1
androidx.navigation:navigation-testing 2.5.3
androidx.core:core-ktx 1.9.0
androidx.lifecycle:lifecycle-runtime-ktx 2.6.1
org.jetbrains.kotlinx:kotlinx-coroutines-android 1.7.1
org.jetbrains.kotlinx:kotlinx-coroutines-test 1.7.1
app.cash.turbine:turbine 1.0.0
androidx.test:core 1.5.0
androidx.test:core-ktx 1.5.0
androidx.test.espresso:espresso-core 3.5.1
androidx.test.ext:junit-ktx 1.1.5
androidx.test:rules 1.5.0
androidx.test:runner 1.5.2
androidx.test:monitor 1.6.1
androidx.test.ext:junit 1.1.5
org.jetbrains.kotlin:kotlin-stdlib-common 1.8.20
org.jetbrains.kotlinx:kotlinx-coroutines-core 1.7.1
org.jetbrains.kotlin:kotlin-test-common 1.8.20
org.junit.jupiter:junit-jupiter 5.9.2
androidx.compose.ui:ui-test-junit4 1.4.3
io.mockk:mockk-android 1.13.4
androidx.test:runner 1.5.2
com.android.application 8.0.2
org.jetbrains.kotlin.android 1.8.20
com.android.library 8.0.2
com.android.test 8.0.2
org.jetbrains.kotlin.jvm 1.8.20
org.sonarqube 4.0.0.2929
org.jetbrains.dokka 1.8.10
org.jlleitschuh.gradle.ktlint 11.3.1
gradle/wrapper/gradle-wrapper.properties
gradle 8.0
I just created a new Android Compose Project. Run it without a library, it's work. Added library to ":app" gradle. Build success, but project build crash
Full log: https://pastebin.com/wHAZUEch
for example:
SelectionHighlightPopUp(popUpLabel = {x,y->
Column {
Text("Title")
Text("x: $x")
}
})
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.