Search code examples
flutterdartflutter-layout

Flutter Aligning label based on the previous Widget's width


Good morning, I have a small issue about widget alignment.

I have a list of images of different sizes and I want to show them in a column with a small label under each one. The label must be aligned at the start based on its relative image.

The label uses the parent's constraints instead of the image's one, how could I constraint it based on the previous widget's width?

What I want to achieve:

Goal

What I get as result:

Output

Code:

import 'package:flutter/material.dart';

class Example extends StatelessWidget {
  const Example({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    const List<Map<String, String>> images = [
      {
        'name': 'img1.jpg',
        'path': 'https://dummyimage.com/238x318/000/fff',
      },
      {
        'name': 'img2.jpg',
        'path': 'https://dummyimage.com/318x300/000/fff',
      },
      {
        'name': 'img3.jpg',
        'path': 'https://dummyimage.com/195x258/000/fff',
      },
      {
        'name': 'img4.jpg',
        'path': 'https://dummyimage.com/336x317/000/fff',
      },
    ];

    return Scaffold(
      appBar: AppBar(
        title: const Text('Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(
          horizontal: 8.0,
        ),
        child: Column(
          children: <Widget>[
            Expanded(
              child: ListView(
                children: images
                    .map((imageItem) => Column(
                          children: <Widget>[
                            Image.network(
                              imageItem['path']!,
                              fit: BoxFit.cover,
                            ),
                            SizedBox(
                              width: double.infinity,
                              child: Text(
                                imageItem['name']!,
                                textAlign: TextAlign.left,
                              ),
                            ),
                          ],
                        ))
                    .toList(),
              ),
            )
          ],
        ),
      ),
    );
  }
}

Solution

  • Remove width from SizedBox and use crossAxisAlignment: CrossAxisAlignment.start, on Column widget.

    return Scaffold(
      appBar: AppBar(
        title: const Text('Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(
          horizontal: 8.0,
        ),
        child: Column(
          children: <Widget>[
            Expanded(
              child: ListView(
                children: images
                    .map((imageItem) => Center(
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,// add this, default is center
                            children: <Widget>[
                              Image.network(
                                imageItem['path']!,
                                fit: BoxFit.cover,
                              ),
                              SizedBox( // you can remove this 
                                child: Text(
                                  imageItem['name']!,
                                  textAlign: TextAlign.left,
                                ),
                              ),
                            ],
                          ),
                        ))
                    .toList(),
              ),
            )
          ],
        ),
      ),
    );