はじめに
Compose でグラフを描きたいとき、どのライブラリを選べばいいのか迷いませんか?
MPAndroidChart は有名ですが、Compose と組み合わせるには工夫が必要です。
今回は Jetpack Compose に最適化されたチャートライブラリ である vico を紹介します。
vicoとは
https://github.com/patrykandpatrick/vico
vicoは、強力で拡張性の高いマルチプラットフォームチャートライブラリです。
以下の特徴があります
- Compose / Compose Multiplatform 対応
- マルチプラットフォーム(Android, Desktop)
- 柔軟なスタイリング
- アニメーションやジェスチャ対応
Composeでグラフを描くという観点でMPAndroid Chartと比較するよ以下のようになると思います
| 観点 | MPAndroidChart(Compose から利用) | Vico |
|---|---|---|
| Compose への組み込み方 |
AndroidView で View をラップして組み込む |
@Composable を直接呼び出す |
| UI ツリーの一貫性 | View と Compose が混在する | Compose のみで完結 |
| スタイル指定 | XML 属性 or View のメソッドで設定 | Compose のパラメータやスロット API で設定 |
今回使ったバージョン・注意点
この記事では v2.2.0 を使用しています。 理由は、私のプロジェクト(compileSdk 35)で問題なくビルドできたためです。
一方で、v2.2.1 の差分を見るとライブラリ側の COMPILE_SDK が 36 に引き上げられており、compileSdk 35 のプロジェクトではビルドが失敗します。
(差分:https://github.com/patrykandpatrick/vico/compare/v2.2.0...v2.2.1)
プロジェクト側の compileSdk をすぐには 36 に上げられない場合は、v2.2.0 を使うのが安全です。
導入方法
まずは、vico の公式サンプルにある JetpackComposeBasicColumnChart をそのまま使って、 棒グラフを 1 つ表示してみます。
依存関係の追加
dependencies {
implementation("com.patrykandpatrick.vico:compose:2.2.0")
}
※ compileSdk は 35 を想定しています。
JetpackComposeBasicColumnChart のコード
@Composable
private fun JetpackComposeBasicColumnChart(
modelProducer: CartesianChartModelProducer,
modifier: Modifier = Modifier,
) {
CartesianChartHost(
chart =
rememberCartesianChart(
rememberColumnCartesianLayer(),
startAxis = VerticalAxis.rememberStart(),
bottomAxis = HorizontalAxis.rememberBottom(),
),
modelProducer = modelProducer,
modifier = modifier,
)
}
@Composable
fun JetpackComposeBasicColumnChart(modifier: Modifier = Modifier) {
val modelProducer = remember { CartesianChartModelProducer() }
LaunchedEffect(Unit) {
modelProducer.runTransaction {
// Learn more: https://patrykandpatrick.com/eji9zq.
columnSeries { series(5, 6, 5, 2, 11, 8, 5, 2, 15, 11, 8, 13, 12, 10, 2, 7) }
}
}
JetpackComposeBasicColumnChart(modelProducer, modifier)
}
※関数名・引数・中身すべて、公式サンプルと同じ形で使っています。
ざっくり何をしているか
- 下の
JetpackComposeBasicColumnChart(modifier: Modifier)-
modelProducerをrememberで生成 -
LaunchedEffectの中でcolumnSeries { … }でグラフ用データを流し込む - 上の private 関数に
modelProducerを渡している
-
- 上の
private fun JetpackComposeBasicColumnChart(modelProducer, modifier)-
CartesianChartHostを使って実際にグラフを描画 -
rememberCartesianChartで- 棒グラフレイヤー(
rememberColumnCartesianLayer()) - Y軸(
VerticalAxis.rememberStart()) - X軸(
HorizontalAxis.rememberBottom()) をまとめて設定している
- 棒グラフレイヤー(
-
画面に表示する
あとは、いつも通り setContent などからこの Composable を呼び出すだけです。
setContent {
MaterialTheme {
JetpackComposeBasicColumnChart()
}
}
ここまでで、軸付きの基本的な棒グラフが表示できるようになります。 次のセクションではVicoでそのようなグラフを描画できるかを見ていきます。
Vicoでできること
ここではサンプルアプリで見ることができる以下グラフをそれぞれ見ていきます
BasicColumnChart
基本的な棒グラフ。
上記で説明した、シンプルなデータを縦棒で可視化する一番ベーシックなチャートです。

BasicLineChart
基本的な折れ線グラフ。
値の推移を線でつなげて、変化の流れを確認したいときに使えます。
BasicComboChart
棒グラフ+折れ線グラフのコンボチャート。
売上と目標値のように、性質の異なる2種類のデータを同じグラフ上で比較したい場面に向いています。
AITestScores
AI と人間の性能比較グラフ。
画像認識・言語理解・プログラミングの 3 分野で、AI のスコアが人間に近づいていく様子を可視化しています。
タップするとスコアを確認できます。
DailyDigitalMediaUse
デジタル機器の利用時間の推移を表すグラフ。
PC・スマホ・その他デバイスなど、カテゴリ別に積み上げて表示することで、1日の中で何にどれくらい時間を使っているかが一目でわかります。
タップすると各デバイスの時間と合計時間を確認できます。
TemperatureAnomalies
地球の気温変化(1940〜2024年頃)を表したチャート。
平年と比べて気温が高い年を緑、低い年を赤で表示し、長期的な傾向(温暖化など)を視覚的に追えるようになっています。
タップすると各年代の気温を表示できます。
ElectricCarSales
電気自動車(EV)の普及を示すグラフ。
2010 年から現在までのシェア拡大を、滑らかな曲線で表現しています。成長トレンドを追う系の指標に使いやすい形です。
タップするとシェア率を表示できます。
RockMetalRatios
岩石中に含まれる金属元素の比率を比較する棒グラフ。
銀・モリブデンなど、複数の元素を並べて可視化することで、カテゴリ間の比較に向いたチャートとなっています。
タップすると金属元素の比率を表示できます。
GoldPrices
金価格の変動チャート。
株価チャートのように時間軸に沿って上下動を表現でき、金融・マーケット系の可視化にそのまま使えそうな例です。
タップするとopening(始値)closing(終値)low(安値)high(高値)の金価格を表示できます。
カスタマイズ・活用例
BasicColumnChartをいじる形でいくつかカスタマイズ例を示します。
Y軸の場所を変える(左 → 右)
@Composable
private fun JetpackComposeBasicColumnChart(
modelProducer: CartesianChartModelProducer,
modifier: Modifier = Modifier,
) {
CartesianChartHost(
chart =
rememberCartesianChart(
rememberColumnCartesianLayer(),
// ★ Y軸を右側に出す(startAxis を消して endAxis を指定)
startAxis = null,
endAxis = VerticalAxis.rememberEnd(),
bottomAxis = HorizontalAxis.rememberBottom(),
),
modelProducer = modelProducer,
modifier = modifier,
)
}
X軸の中身を変える(インデックス → 任意ラベル)
@Composable
private fun JetpackComposeBasicColumnChart(
modelProducer: CartesianChartModelProducer,
modifier: Modifier = Modifier,
) {
val labels = listOf("Jan", "Feb", "Mar", "Apr", "May", "Jun")
CartesianChartHost(
chart =
rememberCartesianChart(
rememberColumnCartesianLayer(),
startAxis = VerticalAxis.rememberStart(),
// ★ X軸ラベルをインデックス→文字列に変換
bottomAxis = HorizontalAxis.rememberBottom(
valueFormatter = { _, x, _ ->
labels.getOrNull(x.toInt()) ?: x.toInt().toString()
},
),
),
modelProducer = modelProducer,
modifier = modifier,
)
}
@Composable
fun JetpackComposeBasicColumnChart(modifier: Modifier = Modifier) {
val modelProducer = remember { CartesianChartModelProducer() }
LaunchedEffect(Unit) {
modelProducer.runTransaction {
// Learn more: https://patrykandpatrick.com/eji9zq.
// ★ X軸ラベルの数に合わせる
columnSeries { series(5, 6, 5, 2, 11, 8) }
}
}
JetpackComposeBasicColumnChart(modelProducer, modifier)
}
valueFormatter は、X軸に表示される数値(0.0, 1.0, …)を任意の文字列に変換するための処理です。
Vico が渡してくる x: Double をインデックスとして扱い、好きなラベル("Jan" など)に置き換えることができます。
これにより、数値のままではなくドメインに合わせたX軸表示が可能になります。
アニメーション(初期アニメーションをオフにする例)
※元のコードはデフォルトで「初回表示時にアニメーション」が有効になっています。
ここではあえてアニメーションをオフにします
@Composable
private fun JetpackComposeBasicColumnChart(
modelProducer: CartesianChartModelProducer,
modifier: Modifier = Modifier,
) {
CartesianChartHost(
chart =
rememberCartesianChart(
rememberColumnCartesianLayer(),
startAxis = VerticalAxis.rememberStart(),
bottomAxis = HorizontalAxis.rememberBottom(),
),
modelProducer = modelProducer,
modifier = modifier,
// ★ 初期アニメーションを無効化
animateIn = false,
)
}
スクロール・ズーム
@Composable
private fun JetpackComposeBasicColumnChart(
modelProducer: CartesianChartModelProducer,
modifier: Modifier = Modifier,
) {
CartesianChartHost(
chart =
rememberCartesianChart(
rememberColumnCartesianLayer(),
startAxis = VerticalAxis.rememberStart(),
bottomAxis = HorizontalAxis.rememberBottom(),
),
modelProducer = modelProducer,
modifier = modifier,
// ★ デフォルトで指定されているがあえて明示的に指定
scrollState = rememberVicoScrollState(),
zoomState = rememberVicoZoomState(),
)
}
Vicoのメリット・デメリット
メリット
-
Jetpack Compose に最適化された API
-
@Composableでそのまま扱えるため、Compose との親和性が非常に高い
-
-
シンプルで扱いやすいコード構造
-
modelProducerとCartesianChartHostを理解すれば基本のグラフはすぐ作れる
-
-
豊富なカスタマイズ性
- 軸の位置、ラベル、アニメーション、スクロール・ズームなどを柔軟に設定できる
-
サンプルが充実
- サンプルアプリで「どんなグラフが作れるか」を一覧で確認できる
-
Compose Multiplatform 対応
- Android だけでなく、デスクトップなどへの展開も視野に入れられる
デメリット
-
日本語の情報が少ない
- まだ国内の利用記事が多くないため、キャッチアップは公式ドキュメント中心になりがち
-
Compose 前提のため、View ベースの既存画面とは併用しづらい
- MPAndroidChart のように View で直接使う構造ではない
-
用意されている範囲を超える深いカスタマイズは難しい
- たとえば「チャートを完全に独自スタイルにしたい」「新しいレイヤーを自作したい」といった高度なカスタマイズは、現状では内部実装の理解を必要とし、難易度が高め
- MPAndroidChart のように View を直接拡張するアプローチとは異なり、拡張ポイントは限定的
最後に
この記事では、Jetpack Compose で扱えるチャートライブラリvicoを紹介しました。
サンプルアプリを眺めるだけでも、棒グラフ・折れ線・複合チャートから長期トレンドの可視化まで、表現の幅広さがわかると思います。
Compose に最適化された API を持つため、これまで AndroidView で MPAndroidChart をラップして使っていた方には、特に一度触ってみてほしいライブラリです。
画面がすべて Compose で完結するため、UI の一貫性を保ちやすく、コードもシンプルになります。
もちろん、Vico にも「用意されている範囲を超えるカスタマイズは難しい」といった特性はありますが、
Compose 前提でチャートを描画したい場合の有力な選択肢であることは間違いありません。
この記事が、グラフライブラリ選定の一助になれば嬉しいです。
興味を持った方は、ぜひサンプルアプリや公式ドキュメントを触ってみてください。
