Repository navigation
Releases: Kyriakos-Georgiopoulos/Grafima
Release list
v1.2.0
Added
-
Grouped and stacked bar charts. Give
BarEntryaseriesIdand neighbouring
entries that share anxLabelbecome one category, drawn side by side or piled
into a single bar according toBarDataSet.mode. Both orientations and RTL are
handled, each bar keeps its own selection and accessibility action, and the
y-axis clears the tallest stack rather than the tallest segment. -
BarEntry.seriesIdandBarEntry.seriesLabel,BarGroupMode,BarDataSet.mode,
ChartStyle.groupSpacingFactor,BarChartSummary,A11yConfig.selectActionLabel,
A11yConfig.clearSelectionLabeland theBarEntry.spokenSeriesLabelextension. Every one is defaulted, so a
dataset that sets no series behaves exactly as it did in 1.1.1. -
LineSeries.dotRadiussizes one series' dots on their own, so a marker can outweigh
the curve it marks instead of drawing at the same weight as the readings around it.
Dp.UnspecifiedkeepsLineChartStyle.dotRadius, matching howouterRadiusdefers
on the pie and radar charts, and0.dpdrops that series' dots while the rest of the
chart keeps theirs.showDotsstill decides whether any dot is drawn at all. -
selectActionLabelandclearSelectionLabelonLineA11yConfig,PieA11yConfig
andRadarA11yConfig, matching the pair the bar chart gained above. These were the
last chart strings a caller could not translate, so a localised app no longer reads
half its charts in the user's language and half in English. Each takes the object it
selects —LineDataPoint,PieEntry,RadarSeries— as the bar chart's takes a
BarEntry, so an override can reach the raw value rather than a pre-formatted label. -
BarLegend, a key mapping each series' colours to itsseriesLabel. A grouped or
stacked chart tells its series apart by colour alone, and the chart names them only
once a bar is selected — at rest, or in a screenshot, a sighted reader had nothing
to read the colours against. Placed by the caller, so the plot keeps its full
height. A dataset with noseriesIddraws no key at all, since the axis already
names those bars, so one call can sit above a chart that switches between single,
grouped and stacked. -
LegendOrientation, shared byBarLegendandLineLegend.
Changed
-
The default
A11yConfig.selectedStateDescriptionnames the series when a bar has
one, so the two bars of a group are told apart. Its signature is unchanged and a
bar without a series is described exactly as before. -
Source breaking.
A11yConfig.barCountDescriptionBuilder: (Int) -> Stringis
removed and replaced bycountDescriptionBuilder: (BarChartSummary) -> String, so
one override covers a dataset whether or not it carries series. A count alone
cannot describe grouping, and a second builder beside it would have left a chart
that localised only the first reverting to English the day it gained a series. The
default wording is unchanged for an ungrouped chart; ragged categories say
"3 bars in 2 groups" rather than claiming a group size they do not share. -
Line chart dots are drawn after every series' area fill rather than inside each
series' own pass, so an earlier series' dots are no longer painted over by a later
series' fill. The plot rectangle and the axis labels now both stand off by the
widest resolved dot radius, so a point on an axis bound is neither clipped by the
composable's edge nor drawn across the labels; a largedotRadiuscosts the plot
that much room on every side. -
Behaviour breaking. The line chart's crosshair reads each series at the x it
stopped on rather than at the selected point's position in the list, and
selectedPointIndexsteps through every x any series reaches, ascending, rather
than the first series' points alone. A one-point "you are here" marker used to be drawn at every x the
first series had a point at; it is now named at its own x and nowhere else, and an x
only it reaches is selectable and announced. Series index-aligned on differing x
values lose the second series' crosshair dot, tooltip line and spoken value: give
both the same x values, or make the second aReferenceLine. This carries no api
diff, so it is the one entry here you cannot catch by diffinglibrary/api/. The
defaultLineA11yConfig.selectedPointDescriptionBuilderfollows the same rule, so a
series with no point at the selected x is no longer announced; an override that
indexespointsby hand keeps its old behaviour and will disagree with what is drawn. -
Binary incompatible.
LineLegendOrientationis now a deprecated typealias of
LegendOrientation, so the two legends name one concept. Kotlin source compiles
unchanged, but the enum class itself leaves the artifact andLineLegend's
descriptor changes, so a module compiled against 1.1.x fails with
NoClassDefFoundErrorrather than theNoSuchMethodErrorthe entry above predicts.
Java callers cannot see a Kotlin typealias at all and must move to
LegendOrientation. Typealiases are absent from both api dumps, so this shim is not
guarded bycheckKotlinAbiand its eventual removal will produce no api diff. -
Bar series that set no colours of their own are given one gradient each from the new
BarDataSet.seriesPaletterather than all sharingdefaultGradientColors. A grouped
or stacked chart tells its series apart by colour alone, so the old default drew bars
and a key that nothing could distinguish. Set the palette to an empty list for the
previous behaviour. A dataset with no series is unaffected. -
Bar gradients with fewer than two colours no longer reach
Brush. A single colour is
widened into a flat gradient and an empty list falls through to the next source; both
previously threw, and a singleColorStoprendered on iOS and desktop while throwing
on Android. -
Binary incompatible.
BarEntry,BarDataSet,ChartStyle,A11yConfig,
LineSeries,LineA11yConfig,PieA11yConfigandRadarA11yConfigeach gained
defaulted constructor parameters, appended so existing positional calls and
destructuring keep their meaning. Apart from the builder rename above
your code compiles unchanged, but Kotlin regenerates a data class's constructor and
copyfor the new arity rather than keeping the old one — the removed signatures
are in the api diff.
Anything compiled against 1.1.1 and run against this release without recompiling
fails withNoSuchMethodError. Recompile dependents; publish no mixed set. -
Source breaking.
LineA11yConfig.selectedPointDescriptionBuildertakes
(Int, List<SelectedPoint>)rather than(Int, List<LineSeries>). The chart now
resolves each series' reading at the selected x before calling it, so an override
gets the points already matched — it cannot disagree with the dots and the tooltip,
and it no longer has to rebuild the shared axis on every crosshair move, which the
default was doing for each snap of a drag. A series with no reading at that x is
absent from the list rather than needing to be filtered out.
Fixed
-
BarLegendkeeps a removed series' row until its bars have finished shrinking,
rather than dropping it the moment the dataset changes. The chart holds a departing
series for the length of its exit animation, so for about a second the key named
fewer colours than were on screen — and on the way in, a row appeared before any bar
it named. The row fades on the chart's ownAnimationConfig, and a departing series
is no longer announced, since it is on its way out of the data. -
A dataset replaced outright no longer draws the old items alongside the new ones.
Departing items were threaded back into an axis they shared no ids with, so
swapping a bar chart's months for quarters drew both sets on one axis and split
the groups between them. Emptying a dataset is still an exit animation: everything
leaving is all there is to draw. Affects the bar, pie, line and radar charts. -
Bar chart hit testing follows the bars while one is animating out. It measured
against the dataset while the draw pass measured against what was on screen, so
every tap landed on the wrong bar for the length of a removal. -
A removed bar's exit animation is no longer restarted from full duration by an
unrelated data change, so a chart updating faster than the animation still lets
its departing bars finish and be released. -
A bar removed while another is selected fades with the rest rather than staying
at full opacity while it animates out. -
Bar chart touch handling followed
ChartStyle.bottomLabelSpaceandtopValueSpace.
Both were read when hit testing but neither restarted the gesture detector, so
changing either left taps aimed at where the bars used to be. -
The horizontal bar chart's selection tooltip is drawn on the end the bar grows
towards. In RTL it was placed past the bar's other end, landing on the axis over
the category labels.TooltipSelectionRendererreads the layout direction from
the draw scope, so a customBarChartSelectionRenderercan do the same without
a signature change.
v1.1.1
Fixed
- Dashed grid lines and dashed reference lines rendered solid on Android below API
28. They were drawn withdrawLine, and the hardware canvas takes a fast path
for it that ignores the path effect; they now go through aPath, which honours
it on every API. Dashed series strokes were never affected. The bar chart's grid
has dashed by default since 1.0.0, so this is the first release where that is
true on an older device.
Changed
-
compileSdkis 36 rather than 37, andminSdk21 rather than 24. AGP writes
compileSdkinto the aar asminCompileSdk, so a library on 37 refuses to build
for any consumer below it — a hard gate, not a warning. Nothing here needed
either floor: the only platform call in the library reads
Settings.Global.ANIMATOR_DURATION_SCALE, which is API 17, and there is no
@RequiresApiorSDK_INTcheck anywhere inlibrary/src.
Reported by Leo Colman in #32 and #33.On API 21 the semantics, accessibility, interaction and layout tests all pass.
The screenshot-based ones cannot run there —captureToImagegoes through
PixelCopy, which is API 26 and up — so CI runs the API-independent classes at
the floor and the full suite on the newer emulator.
v1.1.0
Added
- A
jvmtarget, so the charts run on Compose for Desktop as well as Android and
iOS, and adesktopApprunning the sample in a window. Needs Java 11 or newer,
matching Compose Multiplatform's own desktop artifacts. Reduce motion is the one
thing desktop cannot read for itself: the JVM exposes no portable setting, so
charts animate unless your host providesLocalReduceMotion.
Thanks to Lauren Darcey. LineLegend, a key mapping each series' colour to its label. The chart names
its series only on selection, so a chart at rest — or a screenshot of one — gave
a sighted reader no way to tell overlaid lines apart. Placed by the caller, so
the plot keeps its full width. A series withstrokeGradientColorsgets a
gradient swatch.LineAxisConfig.referenceLinesdraws a threshold across the plot at a fixed axis
value — a target, a limit, or "now" on an axis of hours. EachReferenceLine
names its own axis, so it cannot be given both an x and a y. Drawn over the
series, since a marker behind the data is not a marker. The axis widens to reach
the line, because a target is normally above what has been achieved so far and an
axis fitted to the data would leave it off the chart;includeInRange = false
opts out, and a line still outside the range is skipped rather than clamped.contentDescriptionannounces it to a
screen reader throughLineA11yConfig.referenceLineDescriptionBuilder. See
docs/charts/line.md.LineSeries.dashPatterndashes a stroke, which is what tells a reader a series
is derived rather than measured — a moving average against the readings it
averages.LineLegenddashes that series' swatch to match. The area fill is
never dashed.DashPatternlives inio.grafima.charts, since the bar chart's
grid takes one too.LineChartStyle.valueLabelsprints each point's value beside it, rather than
only in the tooltip once something is selected, which suits a chart of few
points and a screenshot of one. Labels are placed above their point, or below
where there is no room above, and one that would overlap a label already drawn
is dropped rather than stacked on it. See
docs/charts/line.md.LineAxisConfig.xAxisTitleandyAxisTitlename an axis, so the numbers on it
carry their unit. The y title is drawn rotated beside its labels, on the right
in RTL, and both are announced to screen readers. See
docs/charts/line.md.LineAxisConfig.yMin,yMax,xMinandxMaxpin an axis to a fixed range,
so several charts can share one scale instead of each fitting its own data.
A pinned bound is used exactly, and a line that leaves the range is cut where
it crosses the bound rather than flattened along it. A range that cannot work —
inverted, empty, or not finite — falls back to fitting the data. See
docs/charts/line.md.
Changed
LineSeries.strokeGradientColorsnow spans the x axis rather than the series'
own first and last points, so the same color sits at the same x on every series
and on every chart sharing that axis. Identical for a single series whose points
span the whole axis, which is the unpinned case.- The line chart no longer selects a point that lies outside a pinned x range,
by touch or through a screen reader's actions menu. Such points are not drawn,
so selecting one moved the crosshair somewhere nothing was visible. LineAxisConfiggained eight constructor parameters,LineA11yConfigtwo, and
LineChartStyle,LineSeriesandbar.AxisConfigone each, which changes their
generated constructor andcopysignatures. Source-compatible, but an app built against
1.0.0 must be recompiled against this release rather than swapped in place.LineAxisConfig.dashedGridis deprecated in favour ofgridDashPattern, which
says how long a dash is rather than only whether there is one, and says it in dp.
A grid is solid by default as before, anddashedGrid = truestill works — now
as a dp pattern rather than the raw 8px/6px it used, so it is the same size on
every screen: near enough unchanged at 3x, finer below it, desktop included.bar.AxisConfig.dashEffectis deprecated in favour ofgridDashPattern, and now
defaults to null. APathEffectcompares by identity, so every default
AxisConfig()was unequal to every other and defeated the recomposition skipping
the charts rely on — and it could not be constructed at all without the graphics
runtime loaded, which put it out of reach of a plain unit test. An explicit
dashEffectstill wins overgridDashPattern.
If you passeddashEffect = nullto get a solid grid, pass
gridDashPattern = nullinstead. Null now means "unset" and falls through to
the default dash, and the compiler cannot warn you: a deprecated constructor
property warns where it is read, not where it is set.
The default dash is now measured in dp rather than pixels, so it is the same size
on every screen — unchanged at 3x, shorter below it, desktop included.
Fixed
-
A line chart's crosshair tooltip kept the text colour it was first drawn with,
so a theme change while the crosshair was up left the old colour on the new
panel. It is also redrawn now when the display density changes. -
The bar, pie and radar charts kept the selection tooltip they first measured,
so changing its text style or the display density left the old one on screen.
The bar and radar tooltips also kept the old text colour; the pie tooltip kept
the old size.
v1.0.0
First release.
Added
- Five chart types for Compose Multiplatform on Android and iOS, drawn on
Canvas: bar, line,
pie, radar and
gauge. - Accessibility on every chart: one labelled node, the selection published as
stateDescription, and a named custom action per item so screen reader users
never have to hit a target. See docs/ACCESSIBILITY.md. - Entry, morph and exit animations, with items animating out when they leave the
dataset. Collapses to instant when the OS reports reduced motion. - RTL support throughout, including which end of a bar is rounded.
- Hoisted selection — no chart owns its selection state.
- Per-chart
a11yConfig,style,axisConfigandanimationConfigfor
overriding text, geometry and timing.