Skip to main content

2.0.0-alpha.1

For this release, to simplify the library, reduce its size, and prepare for the introduction of candlestick charts and pie charts, we’ve consolidated how charts are created. We’re also introducing split line styles for line charts.

Breaking changesAddressed
Major#413

On this page, we outline the changes included in this update and describe how to migrate from version 1.13.1 to version 2.0.0-alpha.1.

tip

If you need any help updating to Vico 2.0.0-alpha.1 or notice that something is missing from this page, please start a discussion. For bug reports, please open an issue.

warning

With version 1.6.2, Vico’s Maven Central coordinates changed, as described in the release notes. Versions 1.6.2 through 1.13.1 were published under both the new coordinates and the old coordinates, and the releases under the old coordinates had the old package names. We’re ending support for the old package names. Relocation POMs have been published for the old coordinates. If you’re using the old coordinates, when you update to Vico 2.0.0-alpha.1, the download will be redirected, and you’ll get the new package names. In addition to following the migration steps below, you’ll have to migrate to the new package names. We describe how to do so here. If you’re using the new coordinates, continue reading.

All deprecated APIs have been removed, and the minimum SDK version has been increased to 19 (as with AndroidX).

Every chart is now a CartesianCharts with one or more CartesianLayers. There are two CartesianLayers: ColumnCartesianLayer and LineCartesianLayer. CartesianCharts are displayed by CartesianChartHost in Compose, and by CartesianChartView in the view system. There are no other hosts.

Let’s say you had the following in Vico 1.13.1:

Chart(chart = columnChart(...), ...)

In Vico 2.0.0-alpha.1, you’d use this:

CartesianChartHost(chart = rememberCartesianChart(rememberColumnCartesianLayer(...)), ...)

Similarly, consider the following snippet for Vico 1.13.1:

Chart(chart = lineChart(...), ...)

The equivalent in Vico 2.0.0 is the following:

CartesianChartHost(chart = rememberCartesianChart(rememberLineCartesianLayer(...)), ...)

Finally, consider a ComposedChart:

val columnChart = columnChart(...)
val lineChart = lineChart(...)
Chart(chart = remember { columnChart + lineChart }, ...)

Here’s the 2.0.0 equivalent:

CartesianChartHost(chart = rememberCartesianChart(rememberColumnCartesianLayer(), rememberLineCartesianLayer()), ...)

Decorations and persistent Markers are handled by CartesianCharts, not CartesianLayers. Consider this 1.13.1 snippet:

Chart(chart = lineChart(decorations = listOf(...), persistentMarkers = listOf(...)))

In Vico 2.0.0-alpha.1, use this:

CartesianChartHost(
chart = rememberCartesianChart(rememberLineCartesianLayer()),
decorations = listOf(...),
persistentMarkers = listOf(...),
)

If you had a ComposedChart with independently scaled Charts (targetVerticalAxisPosition) in 1.13.1, and one or more of these Charts had a ThresholdLine, then use the new verticalAxisPosition parameter of the ThresholdLine constructor to link the ThresholdLines to the appropriate axes:

ThresholdLine(verticalAxisPosition = AxisPosition.Vertical.Start, ...)

With the exceptions described on this page, CartesianChartHost has the same parameters as the Chart composable did, and CartesianChartView has the same members and XML parameters as ChartView and ComposedChartView did. ColumnCartesianLayer and LineCartesianLayer are largely the same as ColumnChart and ColumnChart (and so rememberColumnCartesianLayer and rememberLineCartesianLayer are largely the same as columnChart and lineChart).

As can be seen in the examples above, CartesianChartView has three new attributes: layers (equivalent to ComposedChartView’s charts), columnLayerStyle (equivalent to columnChartStyle), and columnLayerStyle (equivalent to columnChartStyle). layers accepts a pipe-separated list of column and line. stackedColumn is no longer valid—use the following instead:

<com.patrykandpatrick.vico.views.chart.CartesianChartView
app:layers="column"
app:columnLayerStyle="@style/ColumnLayerStyle"
... />
<style name="ColumnLayerStyle">
<item name="mergeMode">stacked</item>
</style>

The targetVerticalAxisPosition properties and parameters from Vico 1.13.1 are now called verticalAxisPosition. In ColumnCartesianLayer, MergeMode.Stack has been renamed to MergeMode.Stacked for consistency with MergeMode.Grouped. The LineCartesianLayer constructor requires a LineSpec or a list thereof—there’s no longer a default gray line, which was hardly ever appropriate without modification. For all LineSpec properties whose names had the line prefix, the prefix has been removed.

LineSpec now accepts a DynamicShader (property shader), not a color (property lineColor), for the line. For the view system, the color XML attribute remains available. Outside of XML, for a solid color, use ColorShader (DynamicShaders.color in Compose). If your chart has both positive and negative y values, you can use the newly added TopBottomShader for a split style. For example, if you’d like a line to be green for positive y values and red for negative y values, use the following:

TopBottomShader(DynamicShaders.color(Color.Green), DynamicShaders.color(Color.Red))

You can pass in any two DynamicShaders. TopBottomShader works for line backgrounds too. Here’s a simplified version of an example from the sample app (Chart9):

A CartesianChart uses a CartesianChartModel, which is a collection of CartesianLayerModels. Each CartesianLayer has its own CartesianLayerModel (meaning there are two CartesianLayerModels: ColumnCartesianLayerModel and LineCartesianLayerModel). A CartesianChartModel can be created directly or via CartesianChartModelProducer.

Each CartesianLayer looks for an instance of its CartesianLayerModel in the CartesianChartModel. The n​th ColumnCartesianLayerModel is consumed by the n​th ColumnCartesianLayer. The n​th LineCartesianLayerModel is consumed by the n​th LineCartesianLayer. CartesianLayers with no matching CartesianLayerModelss aren’t drawn.

Data is added on a series-by-series basis. Let’s say you used the following for a column chart in Vico 1.13.1:

entryModelOf(1, 7, 3, 4)

In Vico 2.0.0-alpha.1, you’d use this:

CartesianChartModel(ColumnCartesianLayerModel.build { series(1, 7, 3, 4) })

There is, of course, a variant of series that takes both x and y values. You can pass in any two Collections of Numbers, and Vico will take care of the rest. No zipping or mapping is necessary.

CartesianChartModel(ColumnCartesianLayerModel.build { series(x = listOf(1, 2, 3, 4), y = listOf(4, 3, 5, 2)) })

You can add any number of series. This is the equivalent of an entryModelOf call with multiple entriesOf calls inside. For this example, we’re using a LineCartesianLayerModel. For a column chart, you’d simply replace ColumnCartesianLayerModel with LineCartesianLayerModel below—the build DSLs are the same.

CartesianChartModel(
LineCartesianLayerModel.build {
series(x = listOf(1, 2, 3, 4), y = listOf(3, 2, 7, 8))
series(x = listOf(0, 2, 4), y = listOf(3, 2, 2))
series(9, 3, 1, 5)
},
)

In Vico 1.13.1, there was a special kind of ChartEntryModel for ComposedCharts: ComposedChartEntryModel. In Vico 2.0.0-alpha.1, just like a CartesianChart can have multiple CartesianLayers, a CartesianChartModel can have multiple CartesianLayerModels:

CartesianChartModel(
ColumnCartesianLayerModel.build {
series(2, 9, 4, 3)
series(x = listOf(1, 3, 5), y = listOf(2, 3, 3))
},
LineCartesianLayerModel.build {
series(x = listOf(0, 2, 4, 8), y = listOf(3, 2, 7, 8))
series(x = listOf(0, 1, 2), y = listOf(2, 4, 3))
series(9, 3, 1, 5)
},
)

A CartesianChartModel is applied to a chart in the same manner that ChartEntryModels were—use the model parameter of CartesianChartHost and the setModel function of CartesianChartView.

CartesianChartModelProducer is similar to ComposedChartEntryModelProducer. Use build to create it, and run updates via tryRunTransaction or runTransaction. Whereas tryRunTransaction is a normal function, and updates requested by means of it may be rejected if there’s already an update in progress, runTransaction suspends the coroutine from which it’s called until an update can be run. Unless you run data updates in quick succession (multiple times per second), tryRunTransaction is sufficient.

The build, tryRunTransaction, and runTransaction lambdas all give you access to the same DSL. columnSeries and lineSeries extension functions are available for Transaction. These give you access to the same functions as ColumnCartesianLayerModel.build and LineCartesianLayerModel.build.

An empty CartesianChartModelProducer is created as follows:

val modelProducer = CartesianChartModelProducer.build()

You can also run an initial Transaction. Below, the result will be a CartesianChartModel with a three-series ColumnCartesianLayerModel and a two-series LineCartesianLayerModel.

val modelProducer = CartesianChartModelProducer.build {
columnSeries {
series(4, 6, 3, 4)
series(3, 1, 2, 7)
series(x = listOf(0, 3, 6, 9), y = listOf(3, 4, 1, 5))
}
lineSeries {
series(1, 6, 3, 2)
series(x = listOf(1, 2, 3, 4), y = listOf(7, 8, 3, 2))
}
}

As in the case of ComposedChartEntryModelProducer, Transactions are initially empty. For example, the following removes everything but the first column series:

modelProducer.tryRunTransaction {
columnSeries { series(4, 6, 3, 4) }
}

Functions such as populate and remove are no longer available. Generally, when running a Transaction, you should have access to all of your data. It’s simpler and more reliable to map everything than to find the difference. There’s also no getModel function. CartesianChartModelProducers should be passed to hosts, not used to obtain CartesianChartModel instances. If you need a CartesianChartModel instance, use the CartesianChartModel constructor, as shown above.

To link a CartesianChartModelProducer to a chart, use the modelProducer parameter of CartesianChartHost and the modelProducer property of CartesianChartView.

CartesianChartView has new XML attributes for customizing the preview data: previewMinX, previewMaxX, previewMinY, previewMaxY, previewColumnSeriesCount, and previewLineSeriesCount.

AxisValuesOverrider has been renamed to AxisValueOverrider, and all axisValuesOverrider properties and parameters have been renamed to axisValueOverrider. Because there are different CartesianLayerModels, AxisValueOverrider.fixed and AxisValueOverrider.adaptiveYValues now have generic types. Where type inference is possible, no action is required. Elsewhere, specify the CartesianLayerModel subtype corresponding to the CartesianLayer with which the AxisValueOverrider will be used:

AxisValueOverrider.adaptiveYValues<ColumnCartesianLayerModel>(...)

A CartesianChart has one ChartValues instance. ChartValuesManager has been removed. Independent scaling of CartesianLayers remains possible, but rather than having their own ChartValues instances, such CartesianLayers have their own ChartValues.YRanges. ChartValues.YRange has three properties: minY, maxY, and length. The ChartValues.YRange corresponding to a specific VerticalAxis can be retrieved via ChartValues.getYRange. Use null to get the aggregate ChartValues.YRange. Where a MeasureContext instance is available, use the chartValues field to access the CartesianChart’s ChartValues instance. In ValueFormatter (and, by extension, AxisLabelFormatter), the formatValue function has a new parameter, verticalAxisPosition. If you need information on the y range, use the following:

val yRange = chartValues.getYRange(verticalAxisPosition)

In MarkerCorneredShape, tickXKey has been renamed to TICK_X_KEY.

Some APIs have been moved. If you’re left with any broken imports after following the migration steps above, please remove these imports and reimport the APIs in question.

Please see the sample app for examples and consult the API reference for more information on the new APIs. To get in touch with us, follow the links in the green banner at the top of this page.