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 changes | Addressed |
---|---|
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
.
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.
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 CartesianChart
s with one or more CartesianLayer
s. There are two CartesianLayer
s: ColumnCartesianLayer
and LineCartesianLayer
. CartesianChart
s 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
:
- Compose
- Views
Chart(chart = columnChart(...), ...)
<com.patrykandpatrick.vico.views.chart.ChartView
app:chart="column"
app:columnChartStyle="..."
... />
In Vico 2.0.0-alpha.1
, you’d use this:
- Compose
- Views
CartesianChartHost(chart = rememberCartesianChart(rememberColumnCartesianLayer(...)), ...)
<com.patrykandpatrick.vico.views.chart.CartesianChartView
app:layers="column"
app:columnLayerStyle="..."
... />
Similarly, consider the following snippet for Vico 1.13.1
:
- Compose
- Views
Chart(chart = lineChart(...), ...)
<com.patrykandpatrick.vico.views.chart.ChartView
app:chart="line"
app:lineChartStyle="..."
... />
The equivalent in Vico 2.0.0
is the following:
- Compose
- Views
CartesianChartHost(chart = rememberCartesianChart(rememberLineCartesianLayer(...)), ...)
<com.patrykandpatrick.vico.views.chart.CartesianChartView
app:layers="line"
app:lineLayerStyle="..."
... />
Finally, consider a ComposedChart
:
- Compose
- Views
val columnChart = columnChart(...)
val lineChart = lineChart(...)
Chart(chart = remember { columnChart + lineChart }, ...)
<com.patrykandpatrick.vico.views.chart.ComposedChartView
app:charts="column|line"
app:columnChartStyle="..."
app:lineChartStyle="..."
... />
Here’s the 2.0.0
equivalent:
- Compose
- Views
CartesianChartHost(chart = rememberCartesianChart(rememberColumnCartesianLayer(), rememberLineCartesianLayer()), ...)
<com.patrykandpatrick.vico.views.chart.CartesianChartView
app:layers="column|line"
app:columnLayerStyle="..."
app:lineLayerStyle="..."
... />
Decoration
s and persistent Marker
s are handled by CartesianChart
s, not CartesianLayer
s. Consider this 1.13.1
snippet:
- Compose
- Views
Chart(chart = lineChart(decorations = listOf(...), persistentMarkers = listOf(...)))
<com.patrykandpatrick.vico.views.chart.ChartView
app:chart="line"
... />
val chartView = findViewById<ChartView>(...)
(chartView.chart as LineChart).setDecorations(...)
(chartView.chart as LineChart).setPersistentMarkers(...)
In Vico 2.0.0-alpha.1
, use this:
- Compose
- Views
CartesianChartHost(
chart = rememberCartesianChart(rememberLineCartesianLayer()),
decorations = listOf(...),
persistentMarkers = listOf(...),
)
<com.patrykandpatrick.vico.views.chart.CartesianChartView
app:layers="line"
... />
val cartesianChartView = findViewById<CartesianChartView>(...)
chartView.chart?.setDecorations(...)
chartView.chart?.setPersistentMarkers(...)
If you had a ComposedChart
with independently scaled Chart
s (targetVerticalAxisPosition
) in 1.13.1
, and one or more of these Chart
s had a ThresholdLine
, then use the new verticalAxisPosition
parameter of the ThresholdLine
constructor to link the ThresholdLine
s 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:
- Compose
- Views
TopBottomShader(DynamicShaders.color(Color.Green), DynamicShaders.color(Color.Red))
TopBottomShader(ColorShader(Color.GREEN), ColorShader(Color.RED))
You can pass in any two DynamicShader
s. 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 CartesianLayerModel
s. Each CartesianLayer
has its own CartesianLayerModel
(meaning there are two CartesianLayerModel
s: 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 nth ColumnCartesianLayerModel
is consumed by the nth ColumnCartesianLayer
. The nth LineCartesianLayerModel
is consumed by the nth LineCartesianLayer
. CartesianLayer
s with no matching CartesianLayerModels
s 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 Collection
s of Number
s, 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 ComposedChart
s: ComposedChartEntryModel
. In Vico 2.0.0-alpha.1
, just like a CartesianChart
can have multiple CartesianLayer
s, a CartesianChartModel
can have multiple CartesianLayerModel
s:
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 ChartEntryModel
s 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
, Transaction
s 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. CartesianChartModelProducer
s 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 CartesianLayerModel
s, 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 CartesianLayer
s remains possible, but rather than having their own ChartValues
instances, such CartesianLayer
s have their own ChartValues.YRange
s. 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.