はじめに
業務でvicoというグラフ描画ライブラリを使ったので、簡単な実装サンプルを共有します。
Vicoとは
vicoとはグラフを描画するために使用するライブラリです。
Androidでグラフを実装する場合、公式には提供されていないため、ライブラリを頼る必要が、いくつか調べた中で
vicoは複雑なグラフも描画できる、良さそうってことで選択しました。
以下のVico を選択した理由です。
- AndroidView と Jetpack Compose の両方に対応
- メンテナンスが頻繁に行われている
- 公式ドキュメントやサンプルアプリが充実
ちなみにiOSでは、Swift ChartsというApple純正のものが提供されています。
公式ドキュメント:
https://www.patrykandpatrick.com/vico/guide/stable
サンプルアプリもあるので、どんなグラフが描画できるのか簡単にイメージできます。
サンプルアプリ↓

ほぼメンテナンスが止まってしまっているのが 残念で、JetpackCompose に対応していないものもありますが、vico 意外にもいくつかライブラリがあったので載せておきます。
-
- 老舗。今はメンテ止まってしまっている
-
- composeにも対応しているが、これもメンテが止まっている
-
- こちらもcomposeに対応しているが、2年前にメンテが止まっている
Vicoの実装
1. 準備
公式ドキュメントのgetting startedに従い
version catalogに依存関係を定義します。
(version catalogを使わない方法も記載があります。)
注意:
Vico 2系のStable版が2025年1月20日にリリース されました。1系とはクラス構造が大きく異なり、 Breaking Change が発生しているため、移行には注意が必要そうです。今回は2系で動く実装サンプルです。
[versions]
vico = "2.0.1"
[libraries]
vico-compose = { group = "com.patrykandpatrick.vico", name = "compose", version.ref = "vico" }
vico-compose-m2 = { group = "com.patrykandpatrick.vico", name = "compose-m2", version.ref = "vico" }
vico-compose-m3 = { group = "com.patrykandpatrick.vico", name = "compose-m3", version.ref = "vico" }
vico-views = { group = "com.patrykandpatrick.vico", name = "views", version.ref = "vico" }
2. グラフの作成(棒グラフ)
サンプルを参考に、シンプルな 棒グラフ を作成します。
@Composable
fun VicoBarGraph(
modifier: Modifier = Modifier
) {
CartesianChartHost(
chart =
rememberCartesianChart(
rememberColumnCartesianLayer(),
startAxis = VerticalAxis.rememberStart(),
bottomAxis = HorizontalAxis.rememberBottom(),
),
model = CartesianChartModel(
ColumnCartesianLayerModel.build { series(1, 2, 4, 8, 3, 10, 4, 7, 2, 6, 4, 8) }
),
)
}
@Preview
@Composable
fun PreVicoBarGraph() {
VicoBarGraph()
}
出力されるグラフ

3. グラフのカスタマイズ
(1) Y軸のカスタマイズ
y軸のカスタマイズはstartAxisにVerticalAxis渡すことでさまざまなカスタマイズができるようです。
startAxis = VerticalAxis.rememberStart() // rememberStartにさまざまな設定値を渡せる
①y軸のラベルのスタイルを調整
labelにTextComponentを渡す
startAxis = VerticalAxis.rememberStart(
// y軸の目盛ラベルのスタイルを調整
label = rememberTextComponent(
color = Color.Red, // 目盛ラベルの色
textSize = 12.sp, // フォントサイズ
),
)
出力結果:
他にも通常のTextコンポーネントの同じような設定(lineHeight、textAlignment)も調整が可能。

②y軸のスタイルを調整
lineにLineComponentを渡す
startAxis = VerticalAxis.rememberStart(
// y軸のスタイルを調整
line = rememberLineComponent(
fill = fill(Color.Blue), // y軸の色
),
)
出力結果:
他にもy軸の太さなども変更可能。
③y軸の補助線のスタイルを調整
guidelineにLineComponentを渡す
startAxis = VerticalAxis.rememberStart(
// 補助線のスタイルを調整
guideline = rememberLineComponent(
fill = fill(Color.Blue)
),
)
出力結果:
他にも、補助線を実線や点線にすることなどもできます。
④y軸の目盛線のスタイルを調整
tickにLineComponentを渡す
startAxis = VerticalAxis.rememberStart(
// y軸の目盛のスタイルを調整、数字の横に出る線
tick = rememberLineComponent(
fill = fill(Color.Green),
),
)
出力結果:
少しわかりづらいですが、y軸の目盛の線が変わっています。
(2) x軸をカスタマイズ
x軸も同じようにy軸とほぼ同じでbottomAxisにHorizontalAxisを渡すことでさまざまなカスタマイズができるようです。
bottomAxis = HorizontalAxis.rememberBottom(), // rememberBottomにさまざまな設定値を渡せる
①x軸の項目ラベルのスタイルを調整
labelにTextComponentを渡す
bottomAxis = HorizontalAxis.rememberBottom(
// x軸の項目ラベルのスタイルを調整
label = rememberTextComponent(
color = Color.Red, // 項目ラベルの色
textSize = 12.sp, // フォントサイズ
),
)
②x軸のスタイルを調整
lineにLineComponentを渡す
bottomAxis = HorizontalAxis.rememberBottom(
// x軸のスタイルを調整
line = rememberLineComponent(
fill = fill(Color.Red)
),
)
③補助線のスタイルを調整
guidelineにLineComponentを渡す。
bottomAxis = HorizontalAxis.rememberBottom(
// 補助線のスタイルを調整
guideline = rememberLineComponent(
fill = fill(Color.Red),
shape = dashedShape(), // 点線にする
),
)
④x軸のラベル名を任意の文字列に変更
valueFormatterに任意の文字列を渡す。
val xAxisLabels = listOf("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L")
bottomAxis = HorizontalAxis.rememberBottom(
// x軸のラベル名の文字列を調整
valueFormatter = { _, x, _ ->
xAxisLabels[x.toInt() % xAxisLabels.size]
}
)
出力結果:
⑤x軸のラベル名の表示パターン調整
itemPlacerにHorizontalAxis.ItemPlacerを渡す
bottomAxis = HorizontalAxis.rememberBottom(
itemPlacer = HorizontalAxis.ItemPlacer.aligned(
spacing = { 5 }, // x軸のラベルを何個ごとに表示するか
offset = { 1 }, // x軸のラベルのどこから表示を始めるか
),
)
出力結果:
4. 棒線をカスタマイズ
①棒線のスタイルを調整
columnProviderにColumnCartesianLayerを渡すことで調整が可能
rememberColumnCartesianLayer(
columnProvider = ColumnCartesianLayer.ColumnProvider.series(
rememberLineComponent(
fill = fill(Color.Red), // 棒線の色
thickness = 8.dp, // 棒線の太さ
shape = CorneredShape.rounded(
topLeftPercent = 40, // 棒線の角丸
topRightPercent = 40 // 棒線の角丸
),
)
),
),
②棒線の表示間隔を調整
columnCollectionSpacingに値をセット
rememberColumnCartesianLayer(
columnCollectionSpacing = 5.dp, // 各棒線の間のスペース
),
5. グラフのスクロール
グラフをスクロール可能にするには VicoScrollState を設定します。
CartesianChartHost(
model = cartesianChartModel,
scrollState = rememberVicoScrollState(
scrollEnabled = true , // スクロール可能か
initialScroll = Scroll.Absolute.Start, // スクロール可能な場合に初期表示をどこから開始するか
),
)
スクロール動作:

注意点
アニメーション
グラフをアニメーションさせるにはCartesianChartModelProducerから、LaunchedEffectを使ってデータを渡すような実装にする必要があります。しかし、そうすると、プレビューでグラフが確認できなくなるので、以下のようにプレビューとビルド時の処理を分けました。
@Composable
fun VicoBarGraph(
modifier: Modifier = Modifier
) {
val isPreview = LocalInspectionMode.current
val data = listOf(1, 2, 4, 8, 3, 10, 4, 7, 2, 6, 4, 8, 9, 10, 11, 12)
val chart = rememberCartesianChart(
rememberColumnCartesianLayer(),
startAxis = VerticalAxis.rememberStart(),
bottomAxis = HorizontalAxis.rememberBottom()
)
if (isPreview) {
// プレビューでグラフを確認するためにはCartesianChartModelを使う必要がある
val cartesianChartModel = remember {
CartesianChartModel(
ColumnCartesianLayerModel.build { series(*data.toTypedArray()) }
)
}
CartesianChartHost(
chart = chart,
model = cartesianChartModel
)
} else {
// modelProducerを使うと、プレビューではグラフが確認できなくなるが、
// グラフのアニメーションをさせるために必要なので、分ける
val modelProducer = remember { CartesianChartModelProducer() }
LaunchedEffect(Unit) {
modelProducer.runTransaction {
columnSeries { series(*data.toTypedArray()) }
}
}
CartesianChartHost(
chart = chart,
modelProducer = modelProducer,
)
}
}

以上です。
所感
Vicoはグラフの描画自体は比較的簡単に実装可能 です。
しかし、カスタマイズに関しては 公式ドキュメントだけでは分かりにくい部分もあり、サンプルコードを直接読んで試行錯誤する必要がありました。xy軸の細かい設定や、複数のグラフを組みわ合わせることもできるような部分は単純にすごいと思いました。