一、思路来源
Flutter 3.27 会出一个 Flex.spacing 可以添加子项 spacing间距,但是仅仅添加间距不支持 Widget 所以我封装了NFlexSeparated。
Flutter 3.27 的 Flex.spacing:
NFlexSeparated 效果图
二、示例展示
Widget buildSection3() {
final children = List.generate(
4,
(index) => Container(
decoration: BoxDecoration(
color: Colors.green,
// border: Border.all(color: Colors.blue),
),
child: NText("选项_$index"),
)).toList();
Widget separated = Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: VerticalDivider(
color: Colors.red,
width: 1,
indent: 0,
endIndent: 0,
),
);
return Container(
// color: Colors.green,
child: Column(
children: [
NSectionBox(
title: "ListView.separated",
child: Container(
height: 20,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue),
),
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemBuilder: (_, i) => children[i],
separatorBuilder: (_, i) => separated,
itemCount: children.length,
),
),
),
NSectionBox(
title: "NFlexSeparated - separatedBuilder",
child: Container(
height: 30,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue),
),
child: NFlexSeparated(
direction: Axis.horizontal,
spacing: 60,
separatedBuilder: (i) {
final spacing = (i + 1) * 16.0;
return Container(
width: spacing,
color: Colors.yellow,
alignment: Alignment.center,
child: NText(
spacing.toInt().toString(),
style: TextStyle(fontSize: 13),
),
);
// return separated;
},
children: children,
),
),
),
NSectionBox(
title: "NFlexSeparated - spacing: 16",
child: Container(
height: 30,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue),
),
alignment: Alignment.center,
child: NFlexSeparated(
direction: Axis.horizontal,
spacing: 16,
// separatedBuilder: (i) {
// return Container(color: Colors.cyan, width: 12);
// // return separated;
// },
children: children,
),
),
),
NSectionBox(
title: "NFlexSeparated - vertical - separatedBuilder",
child: IntrinsicWidth(
child: NFlexSeparated(
direction: Axis.vertical,
spacing: 60,
separatedBuilder: (i) {
final spacing = (i + 1) * 16.0;
return Container(
height: spacing,
color: Colors.yellow,
alignment: Alignment.center,
child: NText(
spacing.toInt().toString(),
style: TextStyle(fontSize: 13),
),
);
// return separated;
},
children: children,
),
),
),
NSectionBox(
title: "NFlexSeparated - vertical - spacing: 16",
child: IntrinsicWidth(
child: NFlexSeparated(
direction: Axis.vertical,
separatedBuilder: (i) {
final spacing = 16.0;
return Container(
height: spacing,
color: Colors.yellow,
alignment: Alignment.center,
child: NText(
spacing.toInt().toString(),
style: TextStyle(fontSize: 13),
),
);
// return separated;
},
children: children,
),
),
),
NSectionBox(
title: "NFlexSeparated - horizontal",
child: Container(
height: 45,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue),
),
child: IntrinsicHeight(
child: buildFlexSeparated(direction: Axis.horizontal),
),
),
),
NSectionBox(
title: "NFlexSeparated - vertical",
child: Container(
height: 400,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue),
),
child: IntrinsicWidth(
child: buildFlexSeparated(direction: Axis.vertical),
),
),
),
],
),
);
}
/// 带分隔的 Flex
Widget buildFlexSeparated({
required Axis direction,
Alignment? textAlignment = Alignment.center,
double spacing = 0,
Widget Function(int index)? separatedBuilder,
}) {
return NFlexSeparated(
direction: direction,
// crossAxisAlignment: CrossAxisAlignment.start,
spacing: 12,
separatedBuilder: separatedBuilder ??
(i) {
final spacing = 16.0 * (i + 1);
return Container(
width: direction == Axis.horizontal ? spacing : null,
height: direction == Axis.horizontal ? null : spacing,
color: Colors.yellow,
alignment: Alignment.center,
child: NText(
spacing.toInt().toString(),
style: TextStyle(fontSize: 13),
),
);
},
children: [
Flexible(
flex: 1,
child: Container(
color: Colors.red,
alignment: textAlignment,
child: Text(
"flex: 1",
style: TextStyle(fontSize: 13),
),
),
),
Flexible(
flex: 2,
child: Container(
color: Colors.green,
alignment: textAlignment,
child: Text(
"flex: 2",
style: TextStyle(fontSize: 13),
),
),
),
Flexible(
flex: 3,
child: Container(
color: Colors.blue,
alignment: textAlignment,
child: Text(
"flex: 3",
style: TextStyle(fontSize: 18),
),
),
),
Flexible(
flex: 1,
child: Container(
color: Colors.purple,
alignment: textAlignment,
child: Text(
"flex: 1",
style: TextStyle(fontSize: 13),
),
),
),
],
);
}
三、源码 NFlexSeparated
//
// FlexSpacing.dart
// flutter_templet_project
//
// Created by shang on 2024/9/5 16:19.
// Copyright © 2024/9/5 shang. All rights reserved.
//
import 'package:flutter/material.dart';
import 'package:flutter_templet_project/extension/ddlog.dart';
/// 带分隔的 Flex 组件
class NFlexSeparated extends Flex {
NFlexSeparated({
super.key,
required super.direction,
super.mainAxisAlignment,
super.mainAxisSize,
super.crossAxisAlignment,
super.textDirection,
super.verticalDirection,
super.textBaseline, // NO DEFAULT: we don't know what the text's baseline should be
super.clipBehavior,
required List<Widget> children,
double spacing = 0,
Widget Function(int index)? separatedBuilder,
}) : super(
children: [
...children
.map((e) {
final i = children.indexOf(e);
final hasSeparated = e != children.last;
// final separated = separatedBuilder?.call(i);
return <Widget>[
e,
if (hasSeparated)
separatedBuilder?.call(i) ??
SizedBox(
width: direction == Axis.horizontal ? spacing : 0,
height: direction == Axis.vertical ? spacing : 0,
),
];
})
.toList()
.flatMap(),
],
);
}
extension _ListNewExt<E> on List<List<Widget>> {
/// 二维数组降维一维数组
List<E> flatMap() {
final items = this as List<List<E>>;
var list = <E>[];
for (final e in items) {
list.addAll(e);
}
return list;
}
}