Flutter have child match another child's width inside of Column

Viewed 495

I'm trying to create an 'Event' widget that is made out of two text widgets arranged in a column. The width of the Event widget is determined by the first text widget (title). The second text (details) should be constrained by the title's width and wrap to the next line. Here's what I want: https://i.imgur.com/Tksx9ZG.png

I've tried this layout, but the Column's width is set to the detail text's width (largest child)

Column(
  mainAxisAlignment: MainAxisAlignment.start,
  children: [
    Text("Title"),
    Text("Some longer text that should wrap")
  ]
)
3 Answers

So I know I'm late to this question. But I had the same problem with you. After searching around, I'm surprised no one has written a package about this yet.

So I did: https://pub.dev/packages/flex_with_main_child

It'll look something like this:

ColumnWithMainChild(
  mainAxisAlignment: MainAxisAlignment.start,
  mainChild: Text("Title"),
  childrenBelow: [
    Text("Some longer text that should wrap"),
  ]
)

Solution full code:

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final GlobalKey _globalKey = GlobalKey();
  double? titleWidth;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance?.addPostFrameCallback((_) {
      RenderBox renderBox =
          _globalKey.currentContext?.findRenderObject() as RenderBox;
      setState(() {
        titleWidth = renderBox.size.width;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ConstrainedBox(
          constraints: titleWidth == null
              ? const BoxConstraints()
              : BoxConstraints(
                  maxWidth: titleWidth!,
                ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
              Text(
                "Your Title Here",
                key: _globalKey,
                style: const TextStyle(color: Colors.red),
              ),
              const Text("Some longer text that should wrap")
            ],
          ),
        ),
      ),
    );
  }
}

Result:

enter image description here

I was lucky to stumble into Container's width: double.minPositive:

Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          ListTile(
            title: Text('Membership'),
            subtitle: Text('Lorem / \$22 per month'),
          ),
          ListTile(
            title: Text('Start date'),
            subtitle: Text(DateFormat('MMM dd, yyyy').format(DateTime.now())),
          ),
          ListTile(
            title: Text('Card on file'),
            subtitle: Text('XXXX-1111'),
          ),
          Container(
            width: double.minPositive,
            child: ListTile(
              title: Text(
                'Receipt and copy of the membership agreement will be sent to customer\'s email upon purchase.',
                style: Theme.of(context).textTheme.bodySmall,
              ),
            ),
          ),
        ],
      ),

enter image description here

Related