我将我的解决方案提取到 VariableCrossAxisAlignmentRow / Column / Flex 小部件中并发布。
这是我的示例的屏幕截图:
这是代码:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Variable Cross Axis Alignment Flex',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final _alignments = [
CrossAxisAlignment.start,
CrossAxisAlignment.center,
CrossAxisAlignment.end,
CrossAxisAlignment.stretch,
];
final _flexValues = [1, 2, null, 1];
return Scaffold(
appBar: AppBar(
title: Text('Variable Cross Axis Alignment Flex'),
),
body: Center(
child: Container(
decoration: BoxDecoration(border: Border.all()),
width: 400,
height: 700,
child: VariableCrossAxisAlignmentColumn(
flexValues: _flexValues,
alignments: _alignments,
minWidth: 400,
children: [
Container(
width: 280,
color: Colors.red,
height: Size.infinite.height,
child: Text(
'Flex: ${_flexValues[0]}, ${_alignments[0]}',
style: TextStyle(color: Colors.white),
),
),
Container(
width: 280,
height: Size.infinite.height,
color: Colors.blue,
child: Text(
'Flex: ${_flexValues[1]}, ${_alignments[1]}',
style: TextStyle(color: Colors.white),
),
),
Container(
width: 280,
color: Colors.green,
height: 250,
child: Text(
'Flex: ${_flexValues[2]}, ${_alignments[2]}, height: 250',
style: TextStyle(color: Colors.white),
),
),
Container(
width: 280,
height: Size.infinite.height,
color: Colors.black,
child: Text(
'Flex: ${_flexValues[3]}, ${_alignments[3]}',
style: TextStyle(color: Colors.white),
),
),
]))),
);
}
}
class VariableCrossAxisAlignmentFlex extends StatelessWidget {
final List<int?> flexValues;
final Axis direction;
final List<CrossAxisAlignment> alignments;
final List<Widget> children;
final double crossAxisMinSize;
const VariableCrossAxisAlignmentFlex(
{required this.flexValues,
required this.alignments,
required this.children,
required this.direction,
this.crossAxisMinSize = 0.0,
Key? key})
: super(key: key);
Widget makeAligned(Widget widget, CrossAxisAlignment alignment) {
switch (alignment) {
case CrossAxisAlignment.center:
return Center(
child: widget,
);
case CrossAxisAlignment.start:
return Align(
alignment: _startAlignment(),
child: widget,
);
case CrossAxisAlignment.end:
return Align(
alignment: _endAlignment(),
child: widget,
);
case CrossAxisAlignment.stretch:
return widget;
default:
throw 'Alignment not implemented';
}
}
Alignment _startAlignment() {
if (direction == Axis.horizontal) {
return Alignment.topCenter;
} else {
return Alignment.centerLeft;
}
}
Alignment _endAlignment() {
if (direction == Axis.horizontal) {
return Alignment.bottomCenter;
} else {
return Alignment.centerRight;
}
}
Widget _intrinsicWidget({required Widget child}) {
if (direction == Axis.horizontal) {
return IntrinsicHeight(child: child);
} else {
return IntrinsicWidth(child: child);
}
}
Widget _minSizeWidget() {
if (direction == Axis.horizontal) {
return SizedBox(height: crossAxisMinSize);
} else {
return SizedBox(width: crossAxisMinSize);
}
}
@override
Widget build(BuildContext context) {
assert(flexValues.length == children.length);
assert(alignments.length == children.length);
List<Widget> _children = children.asMap().entries.map((MapEntry entry) {
Widget w = entry.value;
int index = entry.key;
int? flexValue = flexValues[index];
CrossAxisAlignment caa = alignments[index];
Widget _aligned = makeAligned(w, caa);
return flexValue == null
? _aligned
: Flexible(flex: flexValue, child: _aligned);
}).toList();
return _intrinsicWidget(
child: Flex(
direction: direction,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [_minSizeWidget(), ..._children],
),
);
}
}
class VariableCrossAxisAlignmentRow extends VariableCrossAxisAlignmentFlex {
VariableCrossAxisAlignmentRow(
{required List<int?> flexValues,
required List<CrossAxisAlignment> alignments,
required List<Widget> children,
double minHeight = 0.0,
Key? key})
: super(
alignments: alignments,
children: children,
flexValues: flexValues,
direction: Axis.horizontal,
crossAxisMinSize: minHeight);
}
class VariableCrossAxisAlignmentColumn extends VariableCrossAxisAlignmentFlex {
VariableCrossAxisAlignmentColumn(
{required List<int?> flexValues,
required List<CrossAxisAlignment> alignments,
required List<Widget> children,
double minWidth = 0.0,
Key? key})
: super(
alignments: alignments,
children: children,
flexValues: flexValues,
direction: Axis.vertical,
crossAxisMinSize: minWidth);
}