Twelve1110
Twelve1110

Reputation: 339

How to control size of a Column inside a SizedBox

I am building a widget to display a chart/graph inside a fixed size window. The chart will be bigger than the window so the solution includes the user being able to scroll the graph widgets around inside a window (you can find details about this in an earlier question I asked about this here).

Part of the layout includes a fixed sized panel created using a SizedBox and, within that, a Column containing rows of widgets that make up the graph. I need the Column to fit its contents tightly so that I can track it's size and, for example, stop the user scrolling up when the last row is visible at the bottom of the SizedBox.

When the size of the children in the Column should make the Column smaller than the SizedBox, the Column is still being forced to be the size of the SizedBox. This is explained in the Flutter documentation here.

According to the Flutter documentation, the solution is:

This can be remedied by wrapping the child SizedBox in a widget that does permit it to be any size up to the size of the parent, such as Center or Align.

I have tried this and it doesn't seem to work. Below is a test app I wrote on DartPad to check this out. If I use either Align or Center as child of SizedBox and parent of the Column widget, the Column is still the same size as the SizedBox. I have also added MainAxisSize.min to the Column, but this doesn't appear to make any difference.

I have considered doing this using a Stack so that the Column is displayed over the SizedBox, rather than as a child of it, but that feels like a bit of a hacky workaround given that the documentation suggests you can control the size of a Column inside a SizedBox.

Does anyone know how I force the Column to be the smallest size it can be inside a SizedBox of fixed size?

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  List<Widget> graphWidgets = const [
    Text(
        'long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text'),
    Text(
        'long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text'),
    Text(
        'long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text'),
  ];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.light(),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: SizedBox(
            // This is the window the chart is displayed in
            height: 200,
            width: 400,
            child: DecoratedBox(
              decoration: BoxDecoration(
                border: Border.all(),
              ),
              child: OverflowBox(
                // Used to prevent graph rows from wrapping in the window
                maxHeight: double.infinity,
                maxWidth: double.infinity,
                alignment: Alignment.topLeft,
                child: DecoratedBox(
                  // Debug widget to show extent of child column
                  decoration: BoxDecoration(
                    border: Border.all(),
                    color: Colors.amber,
                  ),
                  child: Center(
                    // This should allow the Column to be smaller than the SizedBox?
                    child: Column(
                      // This holds the widgets that make up the graph
                      mainAxisSize: MainAxisSize.min,
                      children: graphWidgets,
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Upvotes: 0

Views: 1429

Answers (1)

Twelve1110
Twelve1110

Reputation: 339

As per SayyidJ's reply, the answer is to use a ConstrainedBox rather than a SizedBox. The Column can shrink to fit the contents when it is the child of a ConstrainedBox.

Here is the revised code, which you can run in DartPad, showing this working.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  List<Widget> graphWidgets = const [
    Text(
        'long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text'),
    Text(
        'long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text'),
    Text(
        'long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text-long-line-of-text'),
  ];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.light(),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: ConstrainedBox(
            // This is the window the chart is displayed in
            constraints: BoxConstraints(
              maxHeight: 200,
              maxWidth: 400,
            ),
            child: DecoratedBox(
              decoration: BoxDecoration(
                border: Border.all(),
              ),
              child: OverflowBox(
                // Used to prevent graph rows from wrapping in the window
                maxHeight: double.infinity,
                maxWidth: double.infinity,
                alignment: Alignment.topLeft,
                child: DecoratedBox(
                  // Debug widget to show extent of child column
                  decoration: BoxDecoration(
                    border: Border.all(),
                    color: Colors.amber,
                  ),
                  child: Column(
                    // This holds the widgets that make up the graph
                    mainAxisSize: MainAxisSize.min,
                    children: graphWidgets,
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Upvotes: -2

Related Questions