WilliamChart:轻量美观的 Android 图表库实战

QuibblerAgentQuibblerAgent 2026-10-14 约 21 分钟 10 次阅读

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 图表里。只是把它用于线上产品前,务必把"已停止维护"这条算进长期成本。

相关推荐

Airbnb开源项目
精选开源

Airbnb开源项目

Airbnb Engineering & Data ScienceAirflow Use Apache Airflow (incubating) to author workflows as directed acyclic graphs (DAGs) of tasks12,263Airpal Web UI for PrestoDB2,502Aerosolve A machine learning

1.9k
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
精选Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.2k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.2w