36

At the moment, I am using the following bit of code :

   body: new Container(
            child: new Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
              new MaterialButton(
                height: 120.0,
                child: new Column(
                  children: <Widget>[
                    new Icon(
                      Icons.av_timer,
                      size: 100.0,
                    ),
                    new Text('TIMER'),
                  ],
                ),
                onPressed: null,
              ),
              new MaterialButton(
                height: 120.0,
                child: new Column(
                  children: <Widget>[
                    new Icon(Icons.alarm_add, size: 100.0),
                    new Text('ALARM'),
                  ],
                ),
                onPressed: null,
              )
            ])));

However, I have had to "hardcode" the Icon size to 100.0 and the height of the MaterialButton to 120.0.

I would like the MaterialButton to take as much space as possible (50% of the screen for each), and I would like the Icons to "fit nicely" in that space, ideally along with the Text scaling as well.

I haven't found the way to do that in Flutter yet. If it's not a good idea to try to do this (I would like it to use the entire space of the screen on any device) please let me know why ?

5 Answers 5

52

You can use LayoutBuilder to dynamically get the parent size during build.

A working example :

fit icon

void main() {
  runApp(new MaterialApp(
    home: new TestIcon(),
  ));
}

class TestIcon extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Container(
      color: Colors.white,
      child: new LayoutBuilder(builder: (context, constraint) {
        return new Icon(Icons.access_alarms, size: constraint.biggest.height);
      }),
    );
  }
}
2
  • Nice - how to do with an IconButton.
    – Gerry
    Commented Jan 20, 2023 at 20:26
  • Nice, this is the Flutterest way. Commented Dec 14, 2023 at 23:17
23

Screenshot:

enter image description here


Use FittedBox:

SizedBox.fromSize(
  size: Size.fromRadius(200),
  child: FittedBox(
    child: Icon(Icons.add),
  ),
)
0
4

As for the text sizing, I couldn't find a better way than using some kind of ratio based on the available biggest height.

I don't have the rights to comment yet, so I'll post it here : You can use the minimum between the biggest height and the biggest width.

It will do something similar to BoxFit.contain

boxfit

2
  • I'm not sure how I would use this with fontSizeFactor ?
    – Jackpap
    Commented Aug 22, 2017 at 13:38
  • import "dart:math"; Then fontSizeFactor: min(constraint.biggest.height, constraint.biggest.width) / 30.0 But it's mostly for the Icon. Because size in flutter are using the DPI (density pixel per inch) instead of raw pixels. So fontsSizeFactor will have the same size, whatever the device is. There shouldn't be any need to manually scale the text size Commented Aug 22, 2017 at 13:54
4

As improvement of @CopsOnRoad answer I can suggest use FittedBox with SizedBox.expand like this:

SizedBox.expand(
    child: FittedBox(
        child: Icon(Icons.add),
    ),
)
1
  • This worked for me inside of a Stack widget. Commented Nov 23, 2022 at 13:39
0

Thanks to Darky, I ended up using the LayoutBuilder, along with the Expanded Widget, the Column Widget, and the use of the flex parameter to give the right proportions. As for the text sizing, I couldn't find a better way than using some kind of ratio based on the available biggest height.

body: new Container(
            child: new Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
              new Expanded(
                  child: new MaterialButton(
                      child: new Column(
                        children: <Widget>[
                          new Expanded(
                            flex: 4,
                            child: new LayoutBuilder(
                                builder: (context, constraint) {
                              return new Icon(
                                Icons.timer,
                                size: constraint.biggest.height,
                              );
                            }),
                          ),
                          new Expanded(child:
                              new LayoutBuilder(builder: (context, constraint) {
                            return new Text('TIMER',
                                style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: constraint.biggest.height/30.0));
                          })),
                        ],
                      ),
                      onPressed: () {
                        showTimePicker(
                          context: context,
                          initialTime: new TimeOfDay.now(),
                        );
                      })),
              new Expanded(
                  child: new MaterialButton(
                      child: new Column(
                        children: <Widget>[
                          new Expanded(
                            flex: 4,
                            child: new LayoutBuilder(
                                builder: (context, constraint) {
                                  return new Icon(
                                    Icons.alarm,
                                    size: constraint.biggest.height,
                                  );
                                }),
                          ),
                          new Expanded(child:
                          new LayoutBuilder(builder: (context, constraint) {
                            return new Text('ALARM',
                                style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: constraint.biggest.height/30.0));
                          })),
                        ],
                      ),
                      onPressed: () {
                        showTimePicker(
                          context: context,
                          initialTime: new TimeOfDay.now(),
                        );
                      })),
            ]))

Not the answer you're looking for? Browse other questions tagged or ask your own question.