WilliamChart:轻量美观的 Android 图表库实战
数据可视化是运动、健康、金融、统计类 App 的刚需。MPAndroidChart 功能最全但偏重复杂,WilliamChart 走的则是"轻量 + 美观 + Kotlin 原生"路线——v3 用 Kotlin 完全重写,API 极简,一行 chart.animate(dataSet) 就能把数据画成带动画的折线/柱状/环形图,开箱即得 Material 风格的美观效果。特别提醒:该库已停止维护(README 明确标注 "not longer maintained"),适合学习图表绘制思路或轻量美观场景,生产级重度需求请评估替代方案。本文基于仓库真实 sample,介绍它的依赖、四类图表、动画与交互。参考 GitHub 仓库。
1、概述:WilliamChart 是什么
WilliamChart 是一个 Android 图表库,目标是"快速实现美观且有洞察力的图表"。v3 用 Kotlin 从零重写,主打轻量、模块化、纯 Canvas 自绘,没有一堆第三方依赖,性能好、包体小。它支持四类图表:
图表类型 View 类 适用场景
------------------------------------------------------------------------
折线图 LineChart com.db.williamchart.view.LineChartView 趋势(股价、体重)
柱状图 BarChart com.db.williamchart.view.BarChartView 对比(月销量)
横向柱状图 com.db.williamchart.view.HorizontalBarChartView 排名(榜单)
环形图 DonutChart com.db.williamchart.view.DonutChartView 占比(构成、进度)核心实现(特点):
1. API 极简:数据用 List of Pair,一行 animate() 完成填充 + 动画显示
2. Kotlin 原生:属性式 API(chart.animation.duration = 1000L),DSL 风格
3. 纯 Canvas 自绘,无重量级依赖,包体小、性能好
4. 内置渐变填充、Tooltip 提示框、数据点触摸回调,美观度开箱即用
- 局限:功能不如 MPAndroidChart 全(无饼图、组合图、复杂图例),且已停止维护
2、依赖引入
主包提供四类图表,Tooltip 模块按需引入。注意 groupId 不同:主包是 com.diogobernardino,tooltip 包是 com.diogobernardino.williamchart,容易引错。
// build.gradle (Module)
dependencies {
// 主包:四类图表核心
implementation 'com.diogobernardino:williamchart:3.10.1'
// Tooltip 提示框(可选,按需二选一或都引)
implementation 'com.diogobernardino.williamchart:tooltip-slider:3.10.1' // 滑动浮标
implementation 'com.diogobernardino.williamchart:tooltip-points:3.10.1' // 数据点浮标
// ↑ 注意 tooltip 包 groupId 多了 .williamchart,与主包不同
}核心实现:
1. 主包 com.diogobernardino:williamchart:3.10.1 提供 LineChart/BarChart/DonutChart
2. Tooltip 是独立模块(tooltip-slider / tooltip-points),不引就用不了 SliderTooltip
3. 两个 groupId 不同,主包 com.diogobernardino、tooltip 包 com.diogobernardino.williamchart
4. v3 不兼容 v2,旧项目升级需全面改写 API
3、XML 属性配置
四类图表共用一组通用属性(标签色/字号/字体/坐标轴/网格),各自再加专属样式属性。下面是来自仓库真实 sample 的属性清单:
// 通用属性(所有图表)
app:chart_labelsColor="color" // 标签文字颜色
app:chart_labelsSize="dimension" // 标签字号
app:chart_labelsFont="font" // 标签字体
app:chart_axis="none|x" // 坐标轴显示(none 不显示、x 只显 X 轴)
app:chart_gridEffect="dotted" // 网格线效果(虚线等)
// LineChart 专属
app:chart_lineColor="color" // 线颜色
app:chart_lineThickness="dimension"// 线粗细
app:chart_smoothLine="boolean" // 是否平滑(贝塞尔曲线)
app:chart_pointDrawable="drawable" // 数据点图标
// BarChart / HorizontalBarChart 专属
app:chart_spacing="dimension" // 柱子间距
app:chart_barsColor="color" // 柱子颜色
app:chart_barsBackgroundColor="color" // 柱子背景色
app:chart_barsRadius="dimension" // 柱子圆角
// DonutChart 专属
app:chart_donutThickness="dimension" // 环厚度
app:chart_donutBackgroundColor="color"// 环背景
app:chart_donutRoundCorners="boolean" // 圆角端点
app:chart_donutTotal="float" // 总量(占比基准)核心实现:
1. 样式尽量在 XML 配置(声明式),代码只负责填数据和动画
2. chart_axis="none" 可隐藏坐标轴做纯图形,="x" 只留 X 轴标签
3. chart_smoothLine="true" 让折线变平滑曲线,视觉更柔和
4. chart_donutTotal 决定环形图的"满分"基准,用于按占比绘制弧长
4、折线图 LineChart 实战
折线图是 WilliamChart 最典型的用法,涵盖"XML 配样式 + Kotlin 填数据 + 渐变 + Tooltip + 触摸回调"全流程。数据用 List of Pair(标签 to 数值)。
<!-- XML:折线图样式 -->
<com.db.williamchart.view.LineChartView
android:id="@+id/lineChart"
android:layout_width="match_parent"
android:layout_height="100dp"
app:chart_axis="none"
app:chart_gridEffect="dotted"
app:chart_labelsColor="#FF70977F"
app:chart_labelsSize="10sp"
app:chart_lineColor="#FFFFFF"
app:chart_lineThickness="3dp"
app:chart_smoothLine="true" />// Kotlin:填数据 + 动画 + 渐变 + Tooltip + 触摸(来自仓库 DemoFragment)
// 1. 数据:Pair List(标签 to 数值)
val lineSet = listOf(
"JAN" to 5f, "FEB" to 4.5f, "MAR" to 4.7f,
"APR" to 3.5f, "MAY" to 7.5f, "JUN" to 6f
)
// 2. 折线下方的渐变填充区域
lineChart.gradientFillColors = intArrayOf(
Color.parseColor("#81FFFFFF"),
Color.TRANSPARENT
)
// 3. 动画时长
lineChart.animation.duration = 1000L
// 4. 滑动提示框 Tooltip(需引入 tooltip-slider 包)
lineChart.tooltip = SliderTooltip().also { it.color = Color.WHITE }
// 5. 数据点触摸回调:手指滑过哪个点,显示对应数值
lineChart.onDataPointTouchListener = { index, _, _ ->
val value = lineSet[index].second
// 把 value 显示到 TextView
}
// 6. 一行搞定:填充数据 + 触发动画显示
lineChart.animate(lineSet)核心实现:
1. 数据格式是 List<Pair<String, Float>>,用中缀 to 构造("JAN" to 5f)
2. gradientFillColors 给折线下方加渐变填充,视觉更精致
3. animation.duration 是属性赋值而非 setter,体现 v3 的 Kotlin 风格
4. animate(lineSet) 是核心:一行完成"填数据 + 显示 + 动画",无需 addLine/show 分步
5. onDataPointTouchListener 让图表"可交互",手指滑过数据点即回调其值
5、柱状图与横向柱状图
BarChart 与 HorizontalBarChart 用法完全一致,数据同样是 Pair List,只是方向不同。
<!-- XML:柱状图样式 -->
<com.db.williamchart.view.BarChartView
android:id="@+id/barChart"
android:layout_width="match_parent"
android:layout_height="150dp"
app:chart_axis="x"
app:chart_barsColor="#FFFFFF"
app:chart_barsRadius="4dp"
app:chart_labelsColor="#FF70977F"
app:chart_labelsSize="10sp"
app:chart_spacing="15dp" />// Kotlin:柱状图 + 横向柱状图,animate 一行搞定
val barSet = listOf(
"JAN" to 4F, "FEB" to 7F, "MAR" to 2F,
"APR" to 5F, "MAY" to 2.3F, "JUN" to 4F
)
barChart.animation.duration = 1000L
barChart.animate(barSet)
// 横向柱状图用法完全相同,只是 View 换成 HorizontalBarChartView
horizontalBarChart.animate(listOf("PORRO" to 5F, "FUSCE" to 6.4F, "EGET" to 3F))核心实现:
1. BarChart 与 HorizontalBarChart API 完全一致,仅 XML 的 View 类不同
2. chart_spacing 控制柱间距,chart_barsRadius 让柱子带圆角
3. chart_axis="x" 只显示 X 轴标签(如月份),适合对比类图表
4. 横向柱状图适合"排名/榜单"场景,纵向适合"时间对比"
6、环形图 DonutChart
环形图与折线/柱状不同:数据是纯 Float List(无标签),每个值代表一段弧的占比,颜色用 donutColors 数组指定。
<!-- XML:环形图样式 -->
<com.db.williamchart.view.DonutChartView
android:id="@+id/donutChart"
android:layout_width="match_parent"
android:layout_height="150dp"
app:chart_donutBackgroundColor="#00000000"
app:chart_donutRoundCorners="true"
app:chart_donutThickness="12dp"
app:chart_donutTotal="200" />// Kotlin:环形图,数据是纯 Float List
val donutSet = listOf(20f, 80f, 100f) // 三段弧的值
// 每段弧对应一个颜色
donutChart.donutColors = intArrayOf(
Color.parseColor("#FFFFFF"),
Color.parseColor("#9EFFFFFF"),
Color.parseColor("#8DFFFFFF")
)
donutChart.animation.duration = 1000L
donutChart.animate(donutSet)核心实现:
1. 环形图数据是 List<Float>,不带标签(与折线/柱状的 Pair List 不同)
2. donutColors 数组为每段弧指定颜色,长度应与数据一致
3. chart_donutTotal 是"总量基准",各段值占比据此绘制弧长
4. chart_donutRoundCorners="true" 让弧的端点变圆角,更精致
7、注意事项与选型建议
用 WilliamChart 前,务必了解以下事实,避免踩坑或选错技术栈:
① 已停止维护。README 顶部明确标注 "not longer maintained",issue 不会修复、新系统兼容问题需自行 fork 解决。新项目尤其要慎重,适合"学习图表绘制"或"轻量美观且不追求长期维护"的场景。
② v3 不兼容 v2。v3 完全用 Kotlin 重写,API(animate/属性式)与 v2 完全不同,旧项目升级等于重写。
③ sample 用了过时 API。官方 Demo 用 kotlinx.android.synthetic(已被 Google 废弃),新项目应改用 ViewBinding 或 findViewById。
④ 功能相对精简。没有饼图(Pie)、组合图、复杂图例、手势缩放等高级能力,重度数据可视化力不从心。
⑤ 替代方案(生产级推荐评估):
- MPAndroidChart:功能最全(饼图/组合图/手势缩放),但重、维护也放缓
- AAChartCore:基于 WebView+JS 图表,跨平台、活跃维护
- Vico:Jetpack Compose 时代的现代图表库,Compose 项目首选
- hellocharts-android:轻量、支持手势缩放,折中方案
- 自定义 Canvas:完全可控,简单图表自己画反而最快
8、总结
WilliamChart 的核心价值是"轻量 + 美观 + Kotlin 极简 API"——一行 animate 就能画出带动画的图表,代码读起来也舒服,是学习图表绘制的好范本。但它的"停止维护"是硬伤,选型时必须权衡。
关键要点:
- 四类图:LineChart / BarChart / HorizontalBarChart / DonutChart,View 类在 com.db.williamchart.view
- 用法:XML 配样式 → Kotlin 构造 Pair/Float List → chart.animate(dataSet) 一行显示
- 依赖:主包 com.diogobernardino:williamchart,tooltip 包 groupId 不同(com.diogobernardino.williamchart)
- 交互:animation.duration 控动画、gradientFillColors 加渐变、onDataPointTouchListener 摸数据点
- 数据格式:折线/柱状用 List<Pair>,环形用 List<Float>
- 注意:已停维、v3 不兼容 v2、sample 用了废弃的 synthetic;生产级看 MPAndroidChart / Vico / AAChartCore
对于做运动健康、轻量统计、仪表盘这类"图表不多但要好看"场景的开发者而言,WilliamChart"XML 配样式 + animate 一行渲染"的极简范式依然有学习价值——哪怕最终选别的库,它"用 Pair List 驱动图表 + 属性式 API + 数据点触摸回调"的设计思路,也值得借鉴到自定义 Canvas 图表里。只是把它用于线上产品前,务必把"已停止维护"这条算进长期成本。


