我正在尝试在flutter中创建一个布局,该布局由具有两个子窗口小部件的行组成,其中第一个向左对齐,第二个向右对齐,如果容器太窄,也将包装这些窗口。< / p>
这类似于此处Flutter align two items on extremes - one on the left and one on the right提出的问题,可以使用带有Wrap
的{{1}}小部件来解决。但是,当小部件使用此方法包装时,包装到新运行的正确小部件将不再右对齐。 (screenshots)
我想发生的事情是正确的窗口小部件在包装时保持与右边对齐。在带有flexbox的css中,这可以通过codepen中展示的右窗口小部件上的flex-grow:1或margin-left:auto来实现(调整页面宽度以查看我想要的布局)。>
到目前为止,我已经尝试过:
alignment: WrapAlignment.spaceBetween
小部件中包装正确的小部件以尝试使其在包装时占据剩余宽度,因此我可以在其中对齐,但这会引发错误:Flexible
Incorrect use of ParentDataWidget.
Flexible widgets must be placed inside Flex widgets.
小部件中包装正确的小部件,但这总是扩展到整个宽度,即使屏幕足够宽,两个小部件都位于同一行,也会导致自动包装Align
与CustomMultiChildLayout
配合使用,可以创建正确的布局(screenshot),但是似乎无法根据子窗口小部件来设置窗口小部件的高度高度,强制您使用任意高度值。 docs for MultiChildLayoutDelegate说重写getSize以控制布局的整体大小。布局的大小不能取决于子项的布局属性。
那么有可能创建一个布局,使右小部件在必须包装时仍保持与右边缘对齐吗?
答案 0 :(得分:0)
感谢RémiRousselet的建议,使用自定义RenderBox
是解决布局问题的基本实现(基于Wrap
小部件RenderBox
实现1 {{ 3}})
import 'package:flutter/widgets.dart';
import 'package:flutter/rendering.dart';
import 'dart:math' as math;
class LeftRightAlign extends MultiChildRenderObjectWidget {
LeftRightAlign({
Key key,
@required Widget left,
@required Widget right,
}) : super(key: key, children: [left, right]);
@override
RenderLeftRightAlign createRenderObject(BuildContext context) {
return RenderLeftRightAlign();
}
}
class LeftRightAlignParentData extends ContainerBoxParentData<RenderBox> {}
class RenderLeftRightAlign extends RenderBox
with
ContainerRenderObjectMixin<RenderBox, LeftRightAlignParentData>,
RenderBoxContainerDefaultsMixin<RenderBox, LeftRightAlignParentData> {
RenderLeftRightAlign({
List<RenderBox> children,
}) {
addAll(children);
}
@override
void setupParentData(RenderBox child) {
if (child.parentData is! LeftRightAlignParentData)
child.parentData = LeftRightAlignParentData();
}
@override
void performLayout() {
final BoxConstraints childConstraints = constraints.loosen();
final RenderBox leftChild = firstChild;
final RenderBox rightChild = lastChild;
leftChild.layout(childConstraints, parentUsesSize: true);
rightChild.layout(childConstraints, parentUsesSize: true);
final LeftRightAlignParentData leftParentData = leftChild.parentData;
final LeftRightAlignParentData rightParentData = rightChild.parentData;
final bool wrapped =
leftChild.size.width + rightChild.size.width > constraints.maxWidth;
leftParentData.offset = Offset.zero;
rightParentData.offset = Offset(
constraints.maxWidth - rightChild.size.width,
wrapped ? leftChild.size.height : 0);
size = Size(
constraints.maxWidth,
wrapped
? leftChild.size.height + rightChild.size.height
: math.max(leftChild.size.height, rightChild.size.height));
}
@override
bool hitTestChildren(HitTestResult result, {Offset position}) {
return defaultHitTestChildren(result, position: position);
}
@override
void paint(PaintingContext context, Offset offset) {
defaultPaint(context, offset);
}
}
...
class HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(middle: Text('App')),
child: ListView(children: <Widget>[
Container(
margin: EdgeInsets.symmetric(horizontal: 32, vertical: 16),
child: LeftRightAlign(
left: Text(
'Left Widget',
style: TextStyle(fontSize: 40),
),
right: Text(
'Right Widget',
style: TextStyle(fontSize: 40),
),
),
),
Text('Next Line'),
])
);
}
}