【问题标题】:How to give different elements different cross axis alignment in a Flutter Row如何在 Flutter Row 中为不同的元素提供不同的交叉轴对齐方式
【发布时间】:2021-07-16 21:47:23
【问题描述】:

期望的结果是在容器的左上角有一个图标保持原位(固定顶部,不居中),而多行文本字段在文本变长时扩展,使容器扩展。容器右侧还有一个垂直居中的图标。

如果可以为一行中的不同元素提供不同的 crossAxisAlignment(例如一些开始,一些中心),我将能够解决这个问题。

如果有办法让行元素知道并匹配它们最高兄弟的高度,那么我也可以解决这个问题。

我考虑过this answer,但围绕 Row 的 Container 有一个最小高度,而不是最大高度。当我使用 SizedBox.expand(建议 there)时,我收到 BoxConstraints forces an infinite height 错误。我不想给周围的容器一个最大高度,或者强迫任何东西扩展到最大高度。

【问题讨论】:

    标签: flutter flutter-layout


    【解决方案1】:

    我将我的解决方案提取到 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);
    }
    
    

    【讨论】:

      猜你喜欢
      • 2021-06-02
      • 2019-06-21
      • 1970-01-01
      • 2021-07-11
      • 1970-01-01
      • 2019-12-26
      • 1970-01-01
      • 2021-08-06
      • 2022-09-23
      相关资源
      最近更新 更多