Flutter圈子FlutterFlutter开发圈

Flutter - 教你把KLineChartView移植到Fl

2019-11-17  本文已影响0人  Cosecant

背景

由于需要,最近需要在Flutter中应用股票走势线,寻找了很久Flutter相关第三方库,无果,没有一个是能达到要求的。于是脑子萌发了一个想法,那么我把原生的组件移植过来不也可以吗,只要达到组件的效果即可。 转载请注明出处,谢谢!

那么现在我需要做的是找一个合适的K线的原生代码写的第三方库,原生项目地址:点击查看,感谢KLineChartView的作者。

​ 先看看KLineChartView的效果图:

image.png image.png

万事具备,只欠东风,现在我们把KLineChartView装入Flutter中并使用!

  1. 第一步,新建一个Flutter项目,这里暂且就不叙述了!

  2. 第二步,打开Flutter项目中的android文件夹,并导入KLineChartViewLib!

  3. 第三步,使用原生代码把KLineChartView封装为Flutter的组件,Follow Me!

  1. 第四步,开始编写我的Flutter的KLineChartView,在此我就不再解释下面代码内容,请具体查看代码。

    import 'dart:convert';
    
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/services.dart';
    
    typedef void OnKLineChartViewCreated();
    
    /// 主图类型,默认为MA
    enum KLineMainDrawType { None, MA, BOLL }
    
    /// 副图类型,默认为None
    enum KLineChildDrawPosition { None, MACD, KDJ, RSI, WR }
    
    /// 股票走势图组件
    class KLineChartView extends StatefulWidget {
      KLineChartView({
        Key key,
        this.gridColumnCount = 4,
        this.gridRowCount = 4,
        double width,
        double height,
        BoxConstraints constraints,
        this.backgroundColor = const Color(0xff333333),
        this.padding,
        this.margin,
        this.alignment = Alignment.center,
        @required this.onViewCreated,
      })  : assert(constraints == null || constraints.debugAssertIsValid()),
            assert(onViewCreated != null),
            constraints = (width != null || height != null)
                ? (constraints ??= BoxConstraints())
                        ?.tighten(width: width, height: height) ??
                    BoxConstraints.tightFor(width: width, height: height)
                : (constraints ??= BoxConstraints()),
            super(key: key);
    
      final int gridColumnCount;
      final int gridRowCount;
      final BoxConstraints constraints;
      final Color backgroundColor;
      final EdgeInsets padding;
      final EdgeInsets margin;
      final Alignment alignment;
      final OnKLineChartViewCreated onViewCreated;
    
      @override
      KLineChartViewState createState() => KLineChartViewState();
    }
    
    class KLineChartViewState extends State<KLineChartView> {
      MethodChannel _methodChannel;
    
      /// 添加数据
      /// + [dataList]-数据列表
      /// + [isInitData]-是否是初始数据
      /// + [isHistoryData]-是否是历史数据
      void addData(List<Map<String, dynamic>> dataList,
              {bool isInitData = false, bool isHistoryData = false}) =>
          _methodChannel.invokeMethod('addData', {
            'isInitData': isInitData,
            'isHistoryData': isHistoryData,
            'data': json.encode(dataList)
          });
    
      /// 切换主图
      void changeMainDrawType([KLineMainDrawType type = KLineMainDrawType.MA]) {
        int typeValue = 1;
        if (type == KLineMainDrawType.MA)
          typeValue = 1;
        else if (type == KLineMainDrawType.BOLL)
          typeValue = 2;
        else
          typeValue = 0;
        _methodChannel.invokeMethod('changeMainDrawType', {'type': typeValue});
      }
    
      /// 设置副图
      /// + [position]-副图类型
      void changeChildDraw(
          [KLineChildDrawPosition position = KLineChildDrawPosition.None]) {
        int positionValue = -1;
        if (position == KLineChildDrawPosition.MACD)
          positionValue = 0;
        else if (position == KLineChildDrawPosition.KDJ)
          positionValue = 1;
        else if (position == KLineChildDrawPosition.RSI)
          positionValue = 2;
        else if (position == KLineChildDrawPosition.WR)
          positionValue = 3;
        else
          positionValue = -1;
        _methodChannel.invokeMethod('changeChildDraw', {'position': positionValue});
      }
    
      /// 设置分时线[TRUE]或者K线图[FALSE]
      /// + [isShowMainDrawLine]-TRUE OR FALSE
      void setMainDrawLine([bool isShowMainDrawLine = false]) =>
          _methodChannel.invokeMethod('setMainDrawLine',
              {'isShowMainDrawLine': (isShowMainDrawLine ?? false)});
    
      @override
      Widget build(BuildContext context) => Container(
          constraints: widget.constraints,
          alignment: widget.alignment,
          padding: widget.padding,
          margin: widget.margin,
          color: widget.backgroundColor,
          child: AndroidView(
              viewType: 'plugins.mrper.andrid-view/kline-view',
              creationParams: {
                'gridRowCount': widget.gridColumnCount,
                'gridColumnCount': widget.gridRowCount
              },
              creationParamsCodec: const StandardMessageCodec(),
              onPlatformViewCreated: (int id) {
                _methodChannel =
                    MethodChannel('plugins.mrper.andrid-view/kline-view_$id');
                widget.onViewCreated();
              }));
    }
    
    // class KLineChartViewController {
    //   MethodChannel _methodChannel;
    
    //   KLineChartViewController(int id) {
    //     _methodChannel = MethodChannel('plugins.mrper.andrid-view/kline-view_$id');
    //   }
    
    //   /// 添加数据
    //   /// + [dataList]-数据列表
    //   /// + [isInitData]-是否是初始数据
    //   /// + [isHistoryData]-是否是历史数据
    //   void addData(List<Map<String, dynamic>> dataList,
    //           {bool isInitData = false, bool isHistoryData = false}) =>
    //       _methodChannel.invokeMethod('addData', {
    //         'isInitData': isInitData,
    //         'isHistoryData': isHistoryData,
    //         'data': json.encode(dataList)
    //       });
    
    //   /// 切换主图
    //   void changeMainDrawType([KLineMainDrawType type = KLineMainDrawType.MA]) {
    //     int typeValue = 1;
    //     if (type == KLineMainDrawType.MA)
    //       typeValue = 1;
    //     else if (type == KLineMainDrawType.BOLL)
    //       typeValue = 2;
    //     else
    //       typeValue = 0;
    //     _methodChannel.invokeMethod('changeMainDrawType', {'type': typeValue});
    //   }
    
    //   /// 设置副图
    //   /// + [position]-副图类型
    //   void changeChildDraw(
    //       [KLineChildDrawPosition position = KLineChildDrawPosition.None]) {
    //     int positionValue = -1;
    //     if (position == KLineChildDrawPosition.MACD)
    //       positionValue = 0;
    //     else if (position == KLineChildDrawPosition.KDJ)
    //       positionValue = 1;
    //     else if (position == KLineChildDrawPosition.RSI)
    //       positionValue = 2;
    //     else if (position == KLineChildDrawPosition.WR)
    //       positionValue = 3;
    //     else
    //       positionValue = -1;
    //     _methodChannel.invokeMethod('changeChildDraw', {'position': positionValue});
    //   }
    
    //   /// 设置分时线[TRUE]或者K线图[FALSE]
    //   /// + [isShowMainDrawLine]-TRUE OR FALSE
    //   void setMainDrawLine([bool isShowMainDrawLine = false]) =>
    //       _methodChannel.invokeMethod('setMainDrawLine',
    //           {'isShowMainDrawLine': (isShowMainDrawLine ?? false)});
    // }
    
    
  2. 使用KlineChartView

    class HomePage extends StatefulWidget {
      HomePage({Key key}) : super(key: key);
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      GlobalKey<KLineChartViewState> _klineChartViewKey;
    
      @override
      void initState() {
        _klineChartViewKey = GlobalKey<KLineChartViewState>();
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(title: Text('首页')),
            body: LoaderContainer(
                state: LoaderState.NoAction,
                onReload: () {},
                emptyView: ClassicalNoDataView(
                    spacingFromImageToText: 20,
                    spacingFromTextToButton: 65,
                    onRefresh: () =>
                        showDialog(context: context, child: LoadingDialog()),
                    buttonBackgroundColor: Colors.yellow,
                    buttonBorderRadius: BorderRadius.all(Radius.circular(3))),
                errorView: ClassicalErrorView(
                    spacingFromImageToText: 20,
                    imageWidth: 120,
                    imageHeight: 120,
                    onReload: () {}),
                contentView: Column(children: [
                  Row(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: <Widget>[
                        Padding(
                            padding: const EdgeInsets.symmetric(horizontal: 5),
                            child: Text('主图')),
                        ...['MA', 'BOLL', '隐藏']
                            .map((item) => InkWell(
                                child: Container(
                                    height: 35,
                                    padding:
                                        const EdgeInsets.symmetric(horizontal: 5),
                                    alignment: Alignment.center,
                                    child: Text(item)),
                                onTap: () {
                                  KLineMainDrawType type = KLineMainDrawType.None;
                                  if (item == '隐藏')
                                    type = KLineMainDrawType.None;
                                  else if (item == 'MA')
                                    type = KLineMainDrawType.MA;
                                  else
                                    type = KLineMainDrawType.BOLL;
                                  _klineChartViewKey.currentState
                                      .changeMainDrawType(type);
                                }))
                            .toList()
                      ]),
                  Row(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: <Widget>[
                        Padding(
                            padding: const EdgeInsets.symmetric(horizontal: 5),
                            child: Text('副图')),
                        ...['MACD', 'KDJ', 'RSI', 'WR', '隐藏']
                            .map((item) => InkWell(
                                child: Container(
                                    height: 35,
                                    padding:
                                        const EdgeInsets.symmetric(horizontal: 5),
                                    alignment: Alignment.center,
                                    child: Text(item)),
                                onTap: () {
                                  KLineChildDrawPosition position =
                                      KLineChildDrawPosition.None;
                                  if (item == '隐藏')
                                    position = KLineChildDrawPosition.None;
                                  else if (item == 'MACD')
                                    position = KLineChildDrawPosition.MACD;
                                  else if (item == 'KDJ')
                                    position = KLineChildDrawPosition.KDJ;
                                  else if (item == 'RSI')
                                    position = KLineChildDrawPosition.RSI;
                                  else
                                    position = KLineChildDrawPosition.WR;
                                  _klineChartViewKey.currentState
                                      .changeChildDraw(position);
                                }))
                            .toList()
                      ]),
                  Row(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: <Widget>[
                        ...['分时', 'K线图']
                            .map((item) => InkWell(
                                child: Container(
                                    height: 35,
                                    padding:
                                        const EdgeInsets.symmetric(horizontal: 5),
                                    alignment: Alignment.center,
                                    child: Text(item)),
                                onTap: () {
                                  _klineChartViewKey.currentState
                                      .setMainDrawLine(item == '分时');
                                }))
                            .toList()
                      ]),
                  Expanded(
                      child: KLineChartView(
                          key: _klineChartViewKey,
                          height: MediaQuery.of(context).size.height * 2 / 3,
                          onViewCreated: () {
                            _klineChartViewKey.currentState
                                .addData(TEST_DATA, isInitData: true);
                          }))
                ])));
      }
    }
    
    

    效果图如下:

QQ图片20191117142455.jpg
  1. 到此为止,我们所有的已经实现了,效果还是不错的!

总结

通过这次组件的嵌入化,对PlatformView的了解更加深入了解了。更重点的是,我们要学会使用MethodChannel这个重要的类,如何使用它与Dart代码沟通,如何相互调用。其次是如何创建一个具有Native性质的Flutter组件,玩的愉快!其实我最开始也只是抱着试一试的心态,没想到还可以,也支持视图缩放。

上一篇下一篇

猜你喜欢

热点阅读