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
思路:
1、在 BarChart 外层添加一层 Container,Container外面包裹一层 SingleChildScrollView,scrollDirection 属性设置为 Axis.horizontal,即可实现水平滚动;
2、但是y轴也会跟着一起滚动,所以我们在 SingleChildScrollView 外手写一个y轴,用Row包裹;
这里没什么技巧,主要是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)),
),
),
],
),
],
),
注意层级结构,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 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() 柱条数据配置
),
),
)],
),
),
),
],
),
);
});
}
}
配置过程要注意层级结构,不然可能会报错