一、引入插件

pub.dev:fl_chart package - All Versions

根据项目版本,安装可适配的 fl_chart 版本

二、官网柱状图示例

github参数配置:(x轴、y轴、边框、柱条数据、tooltip等)

https://github.com/imaNNeo/fl_chart/blob/master/repo_files/documentations/bar_chart.md

BarChart(
  BarChartData(
    // read about it in the BarChartData section
  ),
  swapAnimationDuration: Duration(milliseconds: 150), // Optional
  swapAnimationCurve: Curves.linear, // Optional
);

官方给的例子:(柱条数量多时,不能左右滚动)https://github.com/imaNNeo/fl_chart/blob/master/example/lib/presentation/samples/bar/bar_chart_sample1.dart

 三、自定义实现左右滑动 固定y轴

思路:

1、在 BarChart 外层添加一层 Container,Container外面包裹一层 SingleChildScrollView,scrollDirection 属性设置为 Axis.horizontal,即可实现水平滚动;

2、但是y轴也会跟着一起滚动,所以我们在 SingleChildScrollView 外手写一个y轴,用Row包裹;

 1、手写的y轴

        这里没什么技巧,主要是y轴数据的分配:此例中最大值大于5时,也是5等分,四舍五入;小于5则根据最大值分,间隔为1;

            // 手写y轴
            Column(
                children: [
                  const Text('人数',
                      style: TextStyle(color: Color(0xFF999999), fontSize: 11)),
                  Row(
                    children: [
                      Column(
                        children: totalNum >= 5 
                          ? List.generate(5, (index) {
                              return Column(
                                children: [
                                  Text('${(totalNum / 4 * (4 - index)).round()}',
                                    style: const TextStyle(
                                      color: Color(0xFF999999),
                                      fontSize: 11)),
                                  index < 4 ? const SizedBox(height: 25) : const SizedBox()
                                ],
                              );
                            })
                          : List.generate(totalNum + 1, (index) {
                              return Column(
                                children: [
                                  Text('${totalNum - index}',
                                    style: const TextStyle(
                                      color: Color(0xFF999999),
                                      fontSize: 11)),
                                  index < totalNum ? SizedBox(height: (100 / totalNum).toDouble()) : const SizedBox()
                                ],
                              );
                            })
                      ),
                      const SizedBox(width: 4),
                      //垂直分割线
                      const SizedBox(
                        width: 1,
                        height: 161,
                        child: DecoratedBox(
                          decoration: BoxDecoration(color: Color(0xFFEEEEEE)),
                        ),
                      ),
                    ],
                  ),
                ],
              ),
2、实现左右滑动

💎💎注意层级结构,Expanded — SingleChildScrollView — Container — BarChart

            Expanded(
                child: SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: Container(
                        padding: const EdgeInsets.only(top: 10, bottom: 10),
                        width: barList.length * 35 + 220,
                        height: 220,
                        child: BarChart(
                              BarChartData(
                                alignment: BarChartAlignment.spaceEvenly,
                                titlesData: FlTitlesData(
                                  show: true,
                                  topTitles: AxisTitles(
                                    sideTitles: SideTitles(
                                      showTitles: false
                                    ),
                                  ),
                                  bottomTitles: AxisTitles(
                                    sideTitles: SideTitles(
                                      showTitles: true,
                                      reservedSize: 32,
                                      // getTitlesWidget: bottomTitles,  x轴配置
                                    ),
                                  ),
                                  leftTitles: AxisTitles(
                                    sideTitles: SideTitles(
                                      showTitles: false,
                                    ),
                                  ),
                                  rightTitles: AxisTitles(
                                    sideTitles: SideTitles(
                                      showTitles: false
                                    ),
                                  ),
                                ),
                                gridData: FlGridData(show: false),
                                borderData: FlBorderData(
                                  border: const Border(
                                    bottom: BorderSide(color: AppColors.colorFFEEEEEE),
                                  )
                                ),
                                // barGroups: showingGroups()  柱条数据配置
                              ),
                            ),
                      )
                ),
              ),

完整代码结构(x轴、图表数据等需要自己去完善)

import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:oamic_project/common/values/colors.dart';

// 柱状图
class SubjectClassficationBarChart extends StatelessWidget {
  const SubjectClassficationBarChart({super.key});

  @override
  Widget build(BuildContext context) {
    List<int> barList = [10,20,30,4,0,5,50,50,78,45,23,6,21,10];  // 数据列表
    int totalNum = 0;  // 总人数

    return LayoutBuilder(builder: (context, constraints) {
        final maxWidth = constraints.maxWidth;
        return SizedBox(
          width: maxWidth,
          height: 220,
          child: Row(
            children: [
              // 手绘y轴
              Column(
                children: [
                  const Text('人数',
                      style: TextStyle(color: Color(0xFF999999), fontSize: 11)),
                  Row(
                    children: [
                      Column(
                        children: totalNum >= 5 
                          ? List.generate(5, (index) {
                              return Column(
                                children: [
                                  Text('${(totalNum / 4 * (4 - index)).round()}',
                                    style: const TextStyle(
                                      color: Color(0xFF999999),
                                      fontSize: 11)),
                                  index < 4 ? const SizedBox(height: 25) : const SizedBox()
                                ],
                              );
                            })
                          : List.generate(totalNum + 1, (index) {
                              return Column(
                                children: [
                                  Text('${totalNum - index}',
                                    style: const TextStyle(
                                      color: Color(0xFF999999),
                                      fontSize: 11)),
                                  index < totalNum ? SizedBox(height: (100 / totalNum).toDouble()) : const SizedBox()
                                ],
                              );
                            })
                      ),
                      const SizedBox(width: 4),
                      //垂直分割线
                      const SizedBox(
                        width: 1,
                        height: 161,
                        child: DecoratedBox(
                          decoration: BoxDecoration(color: Color(0xFFEEEEEE)),
                        ),
                      ),
                    ],
                  ),
                ],
              ),
              Expanded(
                child: SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: Stack(
                    children: [
                      Container(
                        padding: const EdgeInsets.only(top: 10, bottom: 10),
                        width: barList.length * 35 + 220,
                        height: 220,
                        child: BarChart(
                              BarChartData(
                                alignment: BarChartAlignment.spaceEvenly,
                                titlesData: FlTitlesData(
                                  show: true,
                                  topTitles: AxisTitles(
                                    sideTitles: SideTitles(
                                      showTitles: false
                                    ),
                                  ),
                                  bottomTitles: AxisTitles(
                                    sideTitles: SideTitles(
                                      showTitles: true,
                                      reservedSize: 32,
                                      // getTitlesWidget: bottomTitles,  x轴配置
                                    ),
                                  ),
                                  leftTitles: AxisTitles(
                                    sideTitles: SideTitles(
                                      showTitles: false,
                                    ),
                                  ),
                                  rightTitles: AxisTitles(
                                    sideTitles: SideTitles(
                                      showTitles: false
                                    ),
                                  ),
                                ),
                                gridData: FlGridData(show: false),
                                borderData: FlBorderData(
                                  border: const Border(
                                    bottom: BorderSide(color: AppColors.colorFFEEEEEE),
                                  )
                                ),
                                // barGroups: showingGroups()  柱条数据配置
                              ),
                            ),
                      )],
                  ),
                ),
              ),
            ],
          ),
        );
    });
  }
}

配置过程要注意层级结构,不然可能会报错

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐