Search code examples
flutterflutter-layout

Retrieve the dimensions of a rendered widget


Suppose a Widget has a varying size based on certain properties of the underlying data structure.

May I render a Widget offscreen just to measure its width and height?

How would I do that?

Update - 2020-09-25

I need the dimensions of one rendered widget to assign correct dimension to compute and assign dimensions to the items in a widget tree to get rendered.

Thus I need to retrieve dimensions before I use them in the widget tree.


Solution

  • You can make a widget (either visible or not, use the Opacity widget to hide it if necessary), give it a GlobalKey, and then use that key to get its render object, then get the size from it.

    For example, I added 3 lines of code, to the default "flutter counter example" project. Now clicking on the floating action button will print out the size of the column.

    Sample output: Size(297.0, 741.0)

    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 MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({Key? key, required this.title}) : super(key: key);
    
      final String title;
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      final GlobalKey _key = GlobalKey(); // <--- 1. add this line
      int _counter = 0;
    
      void _incrementCounter() {
        setState(() {
          _counter++;
        });
        print(_key.currentContext?.size);  // <--- 2. add this line
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              key: _key,  // <--- 3. add this line
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.headline4,
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ),
        );
      }
    }