Search code examples
flutterflutter-layout

Flutter: can I use different types of crossAxisAlignment inside one Row?


I have a ListView with dynamic height items. Each item is a Row with 3 elements: Text, Column, Column. ListView looks like this:

enter image description here

Here is the code of my item widget:

class ItemWidget extends StatelessWidget {
  final ItemViewModel model;

  const ItemWidget({Key key, @required this.model}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        SizedBox(width: 16),
        Text(
          model.typeLabel,
        ),
        SizedBox(width: 8),
        Expanded(
          flex: 6,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              SizedBox(height: 4),
              Text(
                'Volume:',
                textAlign: TextAlign.end,
              ),
              SizedBox(height: 2),
              Text(
                model.volume,
                textAlign: TextAlign.end,
              ),
              SizedBox(height: 4),
              Text(
                'Filled:',
                textAlign: TextAlign.end,
              ),
              SizedBox(height: 2),
              Text(
                model.filled,
                textAlign: TextAlign.end,
              ),
              SizedBox(height: 4)
            ],
          ),
        ),
        SizedBox(width: 16),
        Expanded(
            flex: 6,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.end,
              children: [
                SizedBox(height: 4),
                Text(
                  'Price:',
                  textAlign: TextAlign.end,
                ),
                SizedBox(height: 2),
                Text(
                  model.price,
                  textAlign: TextAlign.end,
                ),
                SizedBox(height: 4),
                Text(
                  'Total:',
                  textAlign: TextAlign.end,
                ),
                SizedBox(height: 2),
                Text(
                  model.total,
                  textAlign: TextAlign.end,
                ),
                SizedBox(height: 4),
                Text(
                  'Fee:',
                  textAlign: TextAlign.end,
                ),
                SizedBox(height: 2),
                Text(
                  model.fee,
                  textAlign: TextAlign.end,
                ),
                SizedBox(height: 4),
              ],
            )),
        SizedBox(width: 16),
      ],
    );
  }
}

I want my Column widgets to always be top-aligned, as they are when crossAxisAlignment of Row is CrossAxisAlignment.start. At the same time Text should be centered, as it is now when crossAxisAlignment of Row is CrossAxisAlignment.center. Here is what I want:

enter image description here

How can I achieve this?

Thanks for any help.


Solution

  • The answer: Row widget can't use different crossAxisAlignment types for its children.

    But I found another solution for my layout, with Stack widget in root. Here is working code:

    class ItemWidget extends StatelessWidget {
      final ItemViewModel model;
    
      const ItemWidget({Key key, @required this.model}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Stack(children: [
          Positioned.fill(
            child: Container(
              padding: EdgeInsets.only(left: 16),
              alignment: Alignment.centerLeft,
              child: Text(model.typeLabel),
            ),
          ),
          Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              SizedBox(width: 24),
              Expanded(
                flex: 6,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                    SizedBox(height: 4),
                    Text(
                      'Volume:',
                      textAlign: TextAlign.end,
                    ),
                    SizedBox(height: 2),
                    Text(
                      model.volume,
                      textAlign: TextAlign.end,
                    ),
                    SizedBox(height: 4),
                    Text(
                      'Filled:',
                      textAlign: TextAlign.end,
                    ),
                    SizedBox(height: 2),
                    Text(
                      model.filled,
                      textAlign: TextAlign.end,
                    ),
                    SizedBox(height: 4)
                  ],
                ),
              ),
              SizedBox(width: 16),
              Expanded(
                  flex: 6,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    crossAxisAlignment: CrossAxisAlignment.end,
                    children: [
                      SizedBox(height: 4),
                      Text(
                        'Price:',
                        textAlign: TextAlign.end,
                      ),
                      SizedBox(height: 2),
                      Text(
                        model.price,
                        textAlign: TextAlign.end,
                      ),
                      SizedBox(height: 4),
                      Text(
                        'Total:',
                        textAlign: TextAlign.end,
                      ),
                      SizedBox(height: 2),
                      Text(
                        model.total,
                        textAlign: TextAlign.end,
                      ),
                      SizedBox(height: 4),
                      Text(
                        'Fee:',
                        textAlign: TextAlign.end,
                      ),
                      SizedBox(height: 2),
                      Text(
                        model.fee,
                        textAlign: TextAlign.end,
                      ),
                      SizedBox(height: 4),
                    ],
                  )),
              SizedBox(width: 16),
            ],
          )
        ]);
      }
    }
    

    The result is:

    enter image description here