1

In the code below, a row of two 300x300 boxes (_Box) wrapped with FittedBox shrinks to fit in the screen. As a result, each box becomes smaller than 300x300.

However, if I get the width of a box in the build() method of _Box using RenderBox.size and LayoutBuilder(), the obtained size is 300.0 and Infinity respectively.

How can I get the actual displayed size?

I'd like to get it inside the _Box class, without it getting passed from the parent.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SafeArea(
          child: FittedBox(
            child: Row(
              children: <Widget>[
                _Box(Colors.red),
                _Box(Colors.orange),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class _Box extends StatelessWidget {
  const _Box(this.color);

  final Color color;

  @override
  Widget build(BuildContext context) {
    RenderBox renderBox = context.findRenderObject();
    print(renderBox?.size?.width);  // 300.0

    return LayoutBuilder(
      builder: (_, constraints) {
        print(constraints.maxWidth);  // Infinity

        return Container(
          width: 300,
          height: 300,
          color: color,
        );
      },
    );
  }
}
kaboc
  • 814
  • 1
  • 6
  • 23
  • 1
    Does this answer your question? [How to get a height of a Widget?](https://stackoverflow.com/questions/49307677/how-to-get-a-height-of-a-widget) – Kirill Matrosov Apr 20 '20 at 07:05
  • @kaboc,please check the below solution and let me know in case of concern – Ravindra Kushwaha Apr 20 '20 at 07:20
  • @KirillMatrosov Agh, I've read the answer several months ago but wasn't aware that it could help this time. Thanks. I'll have a look and see if it really works for my case too. – kaboc Apr 20 '20 at 07:54
  • @KirillMatrosov With the same approach, I got `300.0` unfortunately. – kaboc Apr 20 '20 at 08:57
  • Did you find a solution to get the resized size of the widget within a `FittedBox`? – leb1755 Jun 22 '22 at 15:02
  • @leb1755 No, but you reminded me of this question and gave me a chance to look into it again. I wrote a new idea about it [here](https://stackoverflow.com/a/72740742/12086560). I hope it helps you. – kaboc Jun 24 '22 at 07:56

2 Answers2

1

The Flutter constraints object is used to limit how large or small a widget can be rendered, and is usually never really used to get the current size of the widget.

The renderBox.size object is of Size class, and as a result it has both renderBox.size.width and renderBox.size.height as defined getters. Note that these values can only be set once the layout phase of the current view is over: see the findRenderObject() docs page.

This means that you will have to avoid calling findRenderObject() from the build() method. Instead you will have to define a callback function that must execute after the layout process is complete. You can do this using that have widgets that have callback functions like onTap or onSelected. How you implement this and finally get the actual layout size by running the callback function is totally dependent on your use case.

Further recommended reading:

  1. DevelopPaper - Sample code for getting the width and height of screen and widget in Flutter
  2. Flutter on Github - How to get a height of a widget? #16061
  3. Rémi Rousselet's amazing answer explaining his workaround (using an Overlay widget)
Blend3rman
  • 169
  • 13
  • Thanks. I'm conscious about the timing when `renderBox.size.width` is set, which is why I've used `?.` like `renderBox?.size?.width`. I'll read through the linked pages, but can you elaborate how it can actually be achieved? Your answer itself does not give a quick solution for other developers, although I think it contains important information and is helpful even if not the exact answer. – kaboc Apr 20 '20 at 08:11
0

I'll answer my own question, although it is not a direct answer.

I couldn't find a way to get the size shrinked by FittedBox, but I realised that I was able to get around it by using Flexible instead.

SafeArea(
  child: Row(
    children: const [
      Flexible(
        child: _Box(Colors.red),
      ),
      Flexible(
        child: _Box(Colors.orange),
      ),
    ],
  ),
);
@override
Widget build(BuildContext context) {
  return ConstrainedBox(
    constraints: const BoxConstraints(maxWidth: 300.0),
    child: AspectRatio(
      aspectRatio: 1.0,
      child: ColoredBox(color: color),
    ),
  );
}

It still seems impossible to get the size via RenderBox, and it is now possible with LayoutBuilder. But either way, I didn't need them.

The constraints of the two boxies are shrinked by Flexible if a smaller space is available, but they expand as big as the space allows, so I limited the maximum size using ConstrainedBox and AspectRatio.

I didn't have to stick to FittedBox. I think I was obsessed with the idea of using it and couldn't think of other solutions when I posted the question two years ago.

kaboc
  • 814
  • 1
  • 6
  • 23