Flutter 从 0 接入 kline_flutter:K 线图、指标、缩放、滑动和实时数据完整上手
Flutter 从 0 接入 kline_flutter:K 线图、指标、缩放、滑动和实时数据完整上手
本文面向第一次接入 K 线图的小白开发者,从安装
kline_flutter开始,讲清楚如何把接口数据接到图表、如何配置主题和交互、如何处理缩放/滑动/惯性滚动、如何滚动到指定 K 线,以及如何在实时行情里插入新数据。
项目地址:
本文基于 kline_flutter 0.4.0 编写。
一、先看它能做什么
kline_flutter 是一个 Flutter 金融图表库,主要提供:
- K 线蜡烛图
- MA、EMA、BOLL 等主图指标
- VOL、MACD、KDJ、RSI、WR 等副图指标
- 双指缩放
- 缩放时以手指中间的内容为焦点,不是粗暴从左侧缩放
- 横向滑动和松手后的惯性滚动,也就是常说的 fling 效果
- 点击/长按选中 K 线,展示十字线和详情面板
- 外部控制滚动、缩放、选中、指标切换
- socket 推送、分页加载、整窗替换后的主动滚动
- 深度图
DeepChart - 自定义主题、布局、覆盖层、详情面板和绘制 delegate
效果预览素材在 GitHub 仓库里,可以直接点开查看,不需要让 CSDN 转存图片:
二、第一步:安装 package
在你的 Flutter 项目里执行:
flutter pub add kline_flutter
或者手动写入 pubspec.yaml:
dependencies:
kline_flutter: ^0.4.0
然后在业务页面里导入:
import 'package:kline_flutter/kline_flutter.dart';
0.4.0 的 Dart SDK 要求是 ^3.7.0。如果你的项目 Dart 版本太低,需要先升级 Flutter/Dart。
三、第二步:准备你的 K 线数据模型
大部分行情接口都会返回类似这样的字段:
{
"id": 1719801600,
"open": 62000.0,
"high": 62500.0,
"low": 61800.0,
"close": 62300.0,
"vol": 1234.56
}
你可以先定义自己的业务模型。这个模型不需要继承 package 里的任何类:
class Candle {
const Candle({
required this.time,
required this.open,
required this.high,
required this.low,
required this.close,
required this.volume,
this.ma5,
this.ma10,
this.ma30,
});
final DateTime time;
final double open;
final double high;
final double low;
final double close;
final double volume;
final double? ma5;
final double? ma10;
final double? ma30;
String get timeLabel =>
'${time.month.toString().padLeft(2, '0')}-${time.day.toString().padLeft(2, '0')} '
'${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}';
}
如果你的接口字段叫 vol、amount、ts,也没关系。字段名属于业务模型,图表不要求你改成固定名字。
四、第三步:写一个 KLineDataAdapter
kline_flutter 的核心接入思想是 adapter:
你的数据模型保持不变,adapter 负责告诉图表:哪个字段是开盘价、最高价、最低价、收盘价、成交量和时间。
class CandleAdapter extends KLineDataAdapter<Candle> {
const CandleAdapter();
double open(Candle item) => item.open;
double high(Candle item) => item.high;
double low(Candle item) => item.low;
double close(Candle item) => item.close;
double volume(Candle item) => item.volume;
String dateLabel(Candle item) => item.timeLabel;
double? indicatorValue(Candle item, String valueId) {
return switch (valueId) {
KLineDefaultIndicators.ma5 => item.ma5,
KLineDefaultIndicators.ma10 => item.ma10,
KLineDefaultIndicators.ma30 => item.ma30,
_ => null,
};
}
List<KLineDetailEntry> detailEntries(Candle item) {
return [
KLineDetailEntry('时间', item.timeLabel),
KLineDetailEntry('开', item.open.toStringAsFixed(2)),
KLineDetailEntry('高', item.high.toStringAsFixed(2)),
KLineDetailEntry('低', item.low.toStringAsFixed(2)),
KLineDetailEntry('收', item.close.toStringAsFixed(2)),
KLineDetailEntry('量', item.volume.toStringAsFixed(2)),
];
}
}
这里有三个重点:
open/high/low/close/volume/dateLabel是最小必填能力。indicatorValue用来给 MA、EMA、BOLL、MACD 等指标返回数值。detailEntries控制点击或长按选中时详情面板展示哪些字段。
如果你暂时还没有指标数据,可以先不覆盖 indicatorValue,图表仍然可以先展示蜡烛图和成交量。
五、第四步:在页面中显示 K 线图
最小接入只需要 KLineWidget:
class MarketPage extends StatefulWidget {
const MarketPage({super.key});
State<MarketPage> createState() => _MarketPageState();
}
class _MarketPageState extends State<MarketPage> {
final _controller = KLineController(
initialIndicators: const [KLineDefaultIndicators.volumeId],
);
var _candles = <Candle>[];
var _isLoading = false;
Object? _error;
void dispose() {
_controller.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return KLineWidget<Candle>(
controller: _controller,
dataSource: _candles,
adapter: const CandleAdapter(),
isLoading: _isLoading,
error: _error,
onRetry: _loadFirstPage,
initialIndicators: const [KLineDefaultIndicators.volumeId],
);
}
Future<void> _loadFirstPage() async {
// 下一节会补接口接入。
}
}
这一步完成后,你已经有一个默认 K 线 UI:
- 主图蜡烛
- 默认副图
- 长按详情
- 指标区域
- loading / empty / error 状态
- 横向滑动
- 双指缩放
六、第五步:接入接口数据
请求接口、解析 JSON、缓存数据这些属于你的业务层,package 不限制你用 dio、http、retrofit 还是公司内部网络库。你只需要保证最后得到一个List<Candle>,再把它传给 KLineWidget.dataSource。
页面里通常这样更新数据:
Future<void> _loadFirstPage() async {
setState(() {
_isLoading = true;
_error = null;
});
try {
final candles = await loadCandlesFromYourService();
setState(() {
_candles = candles;
});
} catch (error) {
setState(() {
_error = error;
});
} finally {
setState(() {
_isLoading = false;
});
}
}
这里有两个注意点:
- 图表只消费
List<Candle>,不关心你的请求实现。 - 图表本身不强制数组顺序,但你必须保持业务约定一致。本文后面的实时更新示例默认
candles[0]是最新数据,因此scrollToLatest()会回到最左侧最新区域。
七、如何接入指标数据
package 内置的是“指标展示协议”,不是强行替你决定指标怎么计算。你可以:
- 后端直接返回指标值
- 前端自己计算指标值
- 缓存层提前算好指标值
只要最后在 indicatorValue 里按 valueId 返回即可。
内置主图指标:
MAEMABOLL
内置副图指标:
VOLMACDKDJRSIWR
示例:
下面代码假设你的 Candle 已经补了 volumeMa5、volumeMa10、dif、dea、macd 等指标字段。
double? indicatorValue(Candle item, String valueId) {
return switch (valueId) {
KLineDefaultIndicators.ma5 => item.ma5,
KLineDefaultIndicators.ma10 => item.ma10,
KLineDefaultIndicators.ma30 => item.ma30,
KLineDefaultIndicators.volumeMA5 => item.volumeMa5,
KLineDefaultIndicators.volumeMA10 => item.volumeMa10,
KLineDefaultIndicators.dif => item.dif,
KLineDefaultIndicators.dea => item.dea,
KLineDefaultIndicators.macdValue => item.macd,
_ => null,
};
}
如果你想新增一个自己的指标,比如 CCI,可以传入 secondaryIndicators:
KLineWidget<Candle>(
dataSource: _candles,
adapter: const CandleAdapter(),
initialIndicators: const [KLineDefaultIndicators.volumeId, 'cci'],
secondaryIndicators: const [
KLineIndicatorSpec<Candle>(
id: 'cci',
label: 'CCI',
series: [
KLineIndicatorSeries<Candle>(
id: 'cci14',
label: 'CCI14',
colorIndex: 2,
),
],
),
],
)
然后在 adapter 里补:
double? indicatorValue(Candle item, String valueId) {
return switch (valueId) {
'cci14' => item.cci14,
_ => null,
};
}
KLineIndicatorSpec 还能传 renderer,用于柱状图、混合图或特殊指标绘制。普通折线指标不需要自定义 renderer,默认 delegate 会自动绘制。
八、config:KLineWidget 常用配置
KLineWidget 是最快接入入口,常用参数如下:
KLineWidget<Candle>(
controller: _controller,
dataSource: _candles,
adapter: const CandleAdapter(),
theme: const KLineTheme(),
layout: const KLineLayoutConfig(),
behavior: const KLineBehaviorConfig(),
initialIndicators: const [KLineDefaultIndicators.volumeId],
mainIndicators: KLineDefaultIndicators.main<Candle>(),
secondaryIndicators: KLineDefaultIndicators.secondary<Candle>(),
isLoading: _isLoading,
error: _error,
onRetry: _loadFirstPage,
onScroll: _handleScroll,
)
参数说明:
| 参数 | 作用 |
|---|---|
dataSource |
K 线数据数组 |
adapter |
业务模型字段适配器 |
controller |
外部控制缩放、滚动、选中、指标 |
theme |
颜色、线宽、文字等视觉主题 |
layout |
蜡烛宽度、间距、主图高度、副图高度、缩放范围 |
behavior |
是否允许缩放、十字线、滚动时是否清除选中态 |
initialIndicators |
初始打开哪些指标 |
mainIndicators |
主图可选指标列表;不传则使用默认 MA/EMA/BOLL |
secondaryIndicators |
副图可选指标列表;不传则使用默认 VOL/MACD/KDJ/RSI/WR |
isLoading |
是否展示 loading 状态 |
error |
错误状态;有缓存数据时显示顶部错误提示,无数据时显示错误占位 |
onRetry |
默认错误占位里的重试回调 |
onScroll |
用户拖动滚动时回调,可用于分页加载 |
mainIndicators 和 secondaryIndicators 有一个细节:
- 传
null:使用默认指标。 - 传空数组
[]:隐藏对应指标。 - 传自定义数组:只展示你传入的指标。
九、theme:图表颜色和线宽
主题配置集中在 KLineTheme:
const theme = KLineTheme(
candleUpColor: Color(0xFFF14965),
candleDownColor: Color(0xFF00B066),
gridLineColor: Color(0xFFE2E8F0),
crosshairColor: Color(0xFF94A3B8),
backgroundColor: Colors.white,
textColor: Color(0xFF475569),
indicatorColors: [
Color(0xFFFFD700),
Color(0xFF00BFFF),
Color(0xFFDA70D6),
Color(0xFFFF8C00),
],
candleStrokeWidth: 1,
indicatorStrokeWidth: 1,
gridStrokeWidth: 1,
);
字段说明:
| 字段 | 说明 |
|---|---|
candleUpColor |
上涨蜡烛颜色 |
candleDownColor |
下跌蜡烛颜色 |
gridLineColor |
网格线颜色 |
crosshairColor |
十字线颜色 |
backgroundColor |
图表背景色 |
textColor |
坐标轴、指标标题、说明文字颜色 |
indicatorColors |
指标线颜色列表,会按下标循环取色 |
candleStrokeWidth |
蜡烛描边宽度 |
indicatorStrokeWidth |
指标线宽 |
gridStrokeWidth |
网格线宽 |
如果只是改几个颜色,也可以基于已有主题 copyWith:
final darkTheme = const KLineTheme().copyWith(
backgroundColor: const Color(0xFF0F172A),
textColor: const Color(0xFFCBD5E1),
gridLineColor: const Color(0xFF334155),
);
十、layout:蜡烛大小、高度和缩放范围
布局配置集中在 KLineLayoutConfig:
const layout = KLineLayoutConfig(
candleWidth: 8.5,
candleSpacing: 2,
mainChartHeight: 340,
secondaryPaneHeight: 70,
indicatorSelectorHeight: 40,
secondaryContentVerticalPadding: 8,
gridHorizontalCount: 5,
gridVerticalCount: 6,
contentPadding: EdgeInsets.fromLTRB(2, 30, 2, 30),
chartPadding: EdgeInsets.symmetric(horizontal: 2),
minScale: 0.5,
maxScale: 3,
);
字段说明:
| 字段 | 说明 |
|---|---|
candleWidth |
单根蜡烛基础宽度 |
candleSpacing |
蜡烛之间的基础间距 |
mainChartHeight |
主图高度 |
secondaryPaneHeight |
单个副图高度 |
indicatorSelectorHeight |
指标选择器高度 |
secondaryContentVerticalPadding |
副图内容上下留白 |
gridHorizontalCount |
横向网格线数量 |
gridVerticalCount |
纵向网格线数量 |
contentPadding |
主图内容留白 |
chartPadding |
图表整体左右留白 |
minScale |
最小缩放比例 |
maxScale |
最大缩放比例 |
实际蜡烛宽度会根据缩放比例计算:
实际蜡烛宽度 = candleWidth * controller.scale
实际蜡烛间距 = candleSpacing * controller.scale
十一、behavior:缩放、十字线和选中态
交互配置集中在 KLineBehaviorConfig:
const behavior = KLineBehaviorConfig(
enableScale: true,
enableCrosshair: true,
keepCrosshairOnLongPressEnd: true,
clearSelectionOnScroll: true,
);
字段说明:
| 字段 | 说明 |
|---|---|
enableScale |
是否允许双指缩放 |
enableCrosshair |
是否允许点击/长按选中并展示十字线 |
keepCrosshairOnLongPressEnd |
长按结束后是否保留最后一次选中 |
clearSelectionOnScroll |
滚动图表时是否清除当前选中态 |
如果你只想展示静态图表,可以这样关掉交互:
const behavior = KLineBehaviorConfig(
enableScale: false,
enableCrosshair: false,
);
十二、缩放:以手指中间内容为焦点
普通缩放最容易出现的问题是:双指一缩放,图表从左侧或某个固定点缩放,手指下方原本看的 K 线被“甩走”。
kline_flutter 的缩放处理不是简单改 scale,它会同时计算新的 scrollOffset:
- 记录缩放开始时的手势焦点
- 记录焦点对应的内容坐标
- 缩放时计算新的内容宽度
- 把滚动偏移修正到合法范围
- 尽量让手指中间那根 K 线仍然停在手指附近
使用上你不需要自己写这套逻辑,只要保持默认:
KLineWidget<Candle>(
dataSource: _candles,
adapter: const CandleAdapter(),
behavior: const KLineBehaviorConfig(enableScale: true),
)
如果要通过按钮缩放,可以用 KLineController:
OutlinedButton(
onPressed: () {
_controller.setScale((_controller.scale * 1.2).clamp(0.5, 3).toDouble());
},
child: const Text('放大'),
)
手势缩放推荐交给图表内部处理,因为内部会围绕手势焦点修正滚动偏移;按钮缩放没有手势焦点,适合做工具栏快捷操作。
十三、滑动和 fling 效果
图表横向滑动基于 Flutter 自带的 SingleChildScrollView、ScrollController 和滚动物理。
这意味着:
- 手指拖动时,内容跟手移动。
- 手指松开后,Flutter 继续处理惯性滚动,也就是 fling。
- 图表内部只绘制当前可见区附近的布局节点,减少每帧计算压力。
- 固定网格层和滚动内容层分离,网格不会跟着蜡烛一起横向漂移。
滑动监听使用 onScroll:
void _handleScroll(
KLineChartContext<Candle> context,
KLineScrollMetrics metrics,
) {
if (metrics.extentAfter < 40) {
_loadMoreOlder();
}
}
KLineWidget<Candle>(
dataSource: _candles,
adapter: const CandleAdapter(),
onScroll: _handleScroll,
)
KLineScrollMetrics 常用字段:
| 字段 | 说明 |
|---|---|
pixels |
当前滚动偏移 |
minScrollExtent |
最小可滚动位置 |
maxScrollExtent |
最大可滚动位置 |
viewportDimension |
当前视口宽度 |
scrollDelta |
本次滚动变化量 |
extentBefore |
左侧已经滚过的距离 |
extentAfter |
右侧剩余距离 |
一个重要细节:onScroll 只面向用户主动拖动产生的滚动,外部 scrollToIndex、scrollToLatest 这类程序化滚动不会反复触发分页逻辑,避免加载更多被误触发。
十四、滚动到指定位置
外部控制统一通过 KLineController。
final controller = KLineController();
KLineWidget<Candle>(
controller: controller,
dataSource: _candles,
adapter: const CandleAdapter(),
)
滚动到最新:
controller.scrollToLatest();
滚动到指定下标:
controller.scrollToIndex(
20,
alignment: KLineScrollAlignment.center,
);
对齐方式:
KLineScrollAlignment.left
KLineScrollAlignment.center
KLineScrollAlignment.right
选中某个下标:
controller.selectIndex(20);
controller.revealSelected();
读取当前可见范围:
final range = controller.visibleRange;
if (range != null) {
debugPrint('当前可见:${range.start} ~ ${range.end}');
}
常见场景:
- 点击外部列表某一条 K 线,图表滚动到对应下标。
- 多个图表联动,主图滚动后同步副图。
- 搜索某个时间点,定位到那根 K 线。
- 选中后调用
revealSelected(),保证选中项回到可见区域。
十五、实时数据:插入到头部、尾部或指定位置
这里要先讲清楚一个设计原则:
package 不替业务判断数据应该插在哪里。你先更新自己的
List<Candle>,再调用 controller 把目标位置滚进视口。
这样做的好处是边界清晰:
- socket 新 K 线插到哪里,由你的行情数据规则决定。
- 分页加载旧数据追加到哪里,由你的接口顺序决定。
- 图表只负责根据新的
dataSource重新布局和滚动。
1. 最新 K 线插到头部
本文示例约定 candles[0] 是最新数据:
void onSocketCandle(Candle latest) {
setState(() {
_candles = [latest, ..._candles];
});
if (_controller.isFollowingLatest) {
_controller.scrollToLatest();
}
}
如果你希望用户点一个开关后持续跟随最新:
SwitchListTile(
title: const Text('跟随最新'),
value: _controller.isFollowingLatest,
onChanged: (value) {
setState(() {
_controller.setFollowingLatest(value);
});
if (value) {
_controller.scrollToLatest();
}
},
)
2. 加载更多旧 K 线追加到尾部
Future<void> _loadMoreOlder() async {
final older = await fetchOlderCandles();
setState(() {
_candles = [..._candles, ...older];
});
_controller.scrollToIndex(
_candles.length - 1,
alignment: KLineScrollAlignment.right,
);
}
3. 插入到指定位置
比如你收到一条修正数据,要插入到某个下标:
void insertAt(int index, Candle candle) {
final next = [..._candles]..insert(index, candle);
setState(() {
_candles = next;
});
_controller.scrollToIndex(
index,
alignment: KLineScrollAlignment.center,
);
}
如果是替换某一根 K 线:
void replaceAt(int index, Candle candle) {
final next = [..._candles];
next[index] = candle;
setState(() {
_candles = next;
});
_controller.scrollToIndex(
index,
alignment: KLineScrollAlignment.center,
);
}
4. 整个窗口替换后回到指定位置
void replaceWindow(List<Candle> nextWindow) {
setState(() {
_candles = nextWindow;
});
_controller.scrollToIndex(
0,
alignment: KLineScrollAlignment.left,
);
}
完整思路可以看项目里的示例页面:
example/lib/module/usecase/pages/custom_page/custom_live_update_page.dart
十六、Loading / Empty / Error 状态
KLineWidget 已经内置基础状态,你可以直接传:
KLineWidget<Candle>(
dataSource: _candles,
adapter: const CandleAdapter(),
isLoading: _isLoading,
error: _error,
onRetry: _loadFirstPage,
)
也可以自定义:
KLineWidget<Candle>(
dataSource: _candles,
adapter: const CandleAdapter(),
isLoading: _isLoading,
error: _error,
onRetry: _loadFirstPage,
loadingBuilder: (_) => const Center(child: CircularProgressIndicator()),
emptyBuilder: (_) => const Center(child: Text('暂无行情')),
errorBuilder: (_, error, retry) {
return Center(
child: ElevatedButton(
onPressed: retry,
child: Text('加载失败,点击重试:$error'),
),
);
},
)
有缓存数据时,即使 error 不为空,图表仍然可以继续展示旧数据,并在顶部显示错误提示。这适合行情页:刷新失败不应该让用户眼前的旧图表突然消失。
十七、自定义 UI:背景、网格、覆盖层、详情面板
如果默认 UI 已经够用,只配 theme/layout/behavior 即可。
如果你要加业务元素,比如:
- 成本线
- 委托价
- 止盈止损线
- 买卖点标记
- 自定义水印
- 顶部行情条
- 自定义长按详情面板
推荐继承默认 delegate:
class OrderLineDelegate extends KLineDefaultDelegateImpl<Candle> {
const OrderLineDelegate({required super.adapter});
void drawMainChart(
Canvas canvas,
Size size,
KLineChartContext<Candle> context,
) {
super.drawMainChart(canvas, size, context);
final paint = Paint()
..color = const Color(0xFF7C3AED)
..strokeWidth = 1.4;
final y = context.layout.contentPadding.top +
context.layout.contentHeightForMainChart() * 0.62;
canvas.drawLine(Offset(0, y), Offset(size.width, y), paint);
}
}
使用:
KLineWidget<Candle>(
dataSource: _candles,
adapter: const CandleAdapter(),
delegate: const OrderLineDelegate(adapter: CandleAdapter()),
)
这比完全重写图表更轻:默认蜡烛、指标、网格和详情仍然保留,你只追加业务需要的绘制。
完整 demo:
example/lib/module/usecase/pages/custom_page/custom_grid_page.dart
example/lib/module/usecase/pages/custom_page/custom_main_chart_page.dart
example/lib/module/usecase/pages/custom_page/custom_secondary_chart_page.dart
example/lib/module/usecase/pages/custom_page/custom_overlay_page.dart
example/lib/module/usecase/pages/custom_page/custom_selection_view_page.dart
十八、深度图 DeepChart
除了 K 线图,package 还提供累计盘口深度图。
定义盘口模型:
class DepthLevel {
const DepthLevel({
required this.price,
required this.size,
});
final double price;
final double size;
}
定义 adapter:
class DepthAdapter extends DeepChartDataAdapter<DepthLevel> {
const DepthAdapter();
double price(DepthLevel item) => item.price;
double size(DepthLevel item) => item.size;
}
使用:
DeepChart<DepthLevel>(
bids: bids,
asks: asks,
adapter: const DepthAdapter(),
theme: const DeepChartTheme(
bidColor: Color(0xFF00B066),
askColor: Color(0xFFF14965),
),
layout: const DeepChartLayoutConfig(
mainHeight: 240,
bottomHeight: 20,
),
)
深度图默认会:
- 买盘从中线向左展开
- 卖盘从中线向右展开
- 展示累计数量曲线
- 展示底部价格刻度
完整 demo:
example/lib/module/usecase/pages/deep_chart/DeepChartDemoPage.dart
十九、推荐的小白接入顺序
如果你是第一次接入,不要一上来就自定义 delegate。建议按这个顺序:
- 先
flutter pub add kline_flutter - 定义你的
Candle模型 - 写
CandleAdapter - 用
KLineWidget把静态数组展示出来 - 接接口,把返回数据转成
List<Candle> - 确定数组顺序,例如
index 0是否代表最新 - 接入
isLoading/error/onRetry - 补
indicatorValue - 配
theme/layout/behavior - 最后再根据业务需要自定义 delegate
这样接入最稳,遇到问题也最容易定位。
二十、为什么选择 kline_flutter
1. 接入成本低
你不需要把业务模型改成 package 指定的数据结构。只要写一个 KLineDataAdapter<T>,就可以把已有接口模型直接接进图表。
2. 默认能力够完整
默认 UI 已经包含:
- 蜡烛图
- 主图指标
- 副图指标
- 指标切换
- 长按详情
- 缩放
- 横向滑动
- loading / empty / error
对大多数行情页面来说,可以先跑起来,再逐步美化。
3. 交互细节更适合行情场景
双指缩放时会围绕手势焦点修正滚动偏移,用户手指中间看的内容不会突然跳走。
横向滑动走 Flutter 原生滚动物理,松手后有自然的惯性滚动。程序化滚动和用户拖动做了区分,避免分页加载被 scrollToIndex 这类内部滚动误触发。
4. 扩展点清晰
简单改样式,用 KLineTheme。
改蜡烛宽度、高度、缩放范围,用 KLineLayoutConfig。
改缩放和十字线行为,用 KLineBehaviorConfig。
要加业务绘制,继承 KLineDefaultDelegateImpl 并调用 super。
真的要完全接管图表,再直接使用 KLineChart 和 KLineChartDelegate。
5. 适合真实业务里的实时行情
实时 socket、加载更多、整窗替换、插入指定位置,这些都不会被塞进 package 内部变成黑盒。业务先更新自己的数据,再通过 KLineController 滚动到目标位置,职责很清楚。
6. 不只支持 K 线
除了 K 线图,项目也提供 DeepChart,可以把盘口买卖盘接成累计深度图。一个 package 可以覆盖行情页常见的 K 线和深度图两类图表。
总结
从 0 接入 kline_flutter,核心只有三步:
安装 package -> 写 KLineDataAdapter -> 使用 KLineWidget
真正做业务时,再按需补:
接口数据 -> 指标值 -> theme/layout/behavior -> controller -> 自定义 delegate
如果你只是想快速上线一个 K 线行情页,KLineWidget + Adapter 已经够用;如果后面需要成本线、订单标记、自定义详情面板、深度图或实时推送,也都有明确的扩展入口。
完整示例可以直接看仓库:
example/lib/module/usecase/pages/kline/KLineDemoPage.dart
example/lib/module/usecase/pages/custom_page/
example/lib/module/usecase/pages/deep_chart/DeepChartDemoPage.dart
更多推荐
所有评论(0)