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')}';
}

如果你的接口字段叫 volamountts,也没关系。字段名属于业务模型,图表不要求你改成固定名字。


四、第三步:写一个 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
httpretrofit 还是公司内部网络库。你只需要保证最后得到一个
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 返回即可。

内置主图指标:

  • MA
  • EMA
  • BOLL

内置副图指标:

  • VOL
  • MACD
  • KDJ
  • RSI
  • WR

示例:

下面代码假设你的 Candle 已经补了 volumeMa5volumeMa10difdeamacd 等指标字段。


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 用户拖动滚动时回调,可用于分页加载

mainIndicatorssecondaryIndicators 有一个细节:

  • 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 自带的 SingleChildScrollViewScrollController 和滚动物理。

这意味着:

  • 手指拖动时,内容跟手移动。
  • 手指松开后,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 只面向用户主动拖动产生的滚动,外部 scrollToIndexscrollToLatest 这类程序化滚动不会反复触发分页逻辑,避免加载更多被误触发。


十四、滚动到指定位置

外部控制统一通过 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。建议按这个顺序:

  1. flutter pub add kline_flutter
  2. 定义你的 Candle 模型
  3. CandleAdapter
  4. KLineWidget 把静态数组展示出来
  5. 接接口,把返回数据转成 List<Candle>
  6. 确定数组顺序,例如 index 0 是否代表最新
  7. 接入 isLoading/error/onRetry
  8. indicatorValue
  9. theme/layout/behavior
  10. 最后再根据业务需要自定义 delegate

这样接入最稳,遇到问题也最容易定位。


二十、为什么选择 kline_flutter

1. 接入成本低

你不需要把业务模型改成 package 指定的数据结构。只要写一个 KLineDataAdapter<T>,就可以把已有接口模型直接接进图表。

2. 默认能力够完整

默认 UI 已经包含:

  • 蜡烛图
  • 主图指标
  • 副图指标
  • 指标切换
  • 长按详情
  • 缩放
  • 横向滑动
  • loading / empty / error

对大多数行情页面来说,可以先跑起来,再逐步美化。

3. 交互细节更适合行情场景

双指缩放时会围绕手势焦点修正滚动偏移,用户手指中间看的内容不会突然跳走。

横向滑动走 Flutter 原生滚动物理,松手后有自然的惯性滚动。程序化滚动和用户拖动做了区分,避免分页加载被 scrollToIndex 这类内部滚动误触发。

4. 扩展点清晰

简单改样式,用 KLineTheme

改蜡烛宽度、高度、缩放范围,用 KLineLayoutConfig

改缩放和十字线行为,用 KLineBehaviorConfig

要加业务绘制,继承 KLineDefaultDelegateImpl 并调用 super

真的要完全接管图表,再直接使用 KLineChartKLineChartDelegate

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
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐