32

How to get widget's absolute coordinates on a screen in Flutter?

Or its offset in a parent

Example:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Simple app',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SimpleScreen(
        title: 'Simple screen',
      ),
    );
  }
}

class SimpleScreen extends StatefulWidget {
  final String title;

  SimpleScreen({Key key, this.title}) : super(key: key);

  @override
  _SimpleScreenState createState() => new _SimpleScreenState();
}

class _SimpleScreenState extends State<SimpleScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Container(
          width: 48.0,
          height: 48.0,
          color: Colors.blue,
        ),
      ),
    );
  }
}

Goal is to get Container's offset in parent. If Center's size is 48.0, then Container's offset in Center's parent/root

Condition: you don't know the wrapper layout (it's a library widget), should be flexible, without hardcoded values

Thanks

Ihor Klimov
  • 839
  • 4
  • 15
  • 23
  • That example doesn't help at all. What are you trying to do with this information ? – Rémi Rousselet May 13 '18 at 14:56
  • Hi check out this issue : https://github.com/flutter/flutter/issues/1234 Looks like there's a https://docs.flutter.io/flutter/widgets/CompositedTransformFollower-class.html that mayhelp with this. :) i've not tried it myself though. – behzad.robot May 13 '18 at 18:45
  • @behzad.robot `CompositedTransformFollower` solves the specific problem mentioned in [that GitHub issue](https://github.com/flutter/flutter/issues/1234). It won't get the absolute coordinates of a widget. – jamesdlin Jun 24 '19 at 21:48

3 Answers3

39

You can use this extension I wrote (requires Dart 2.6):

extension GlobalKeyExtension on GlobalKey {
  Rect? get globalPaintBounds {
    final renderObject = currentContext?.findRenderObject();
    final translation = renderObject?.getTransformTo(null).getTranslation();
    if (translation != null && renderObject?.paintBounds != null) {
      final offset = Offset(translation.x, translation.y);
      return renderObject!.paintBounds.shift(offset);
    } else {
      return null;
    }
  }
}

Example how to use it:

final containerKey = GlobalKey();

Container(
  key: containerKey,
  width: 100,
  height: 50,
)

void printWidgetPosition() {
  print('absolute coordinates on screen: ${containerKey.globalPaintBounds}');
}
Rody Davis
  • 1,340
  • 11
  • 20
vovahost
  • 30,160
  • 14
  • 104
  • 106
  • how can I call ```Rect get containerRect => containerKey.globalPaintBounds;``` inside a function. I need to get position of a animated container periodically so I want to call it inside Timer.Periodic ? – Tushar Gautam Sep 30 '20 at 07:42
  • @TusharGautam Just save the extension from my answer to a dart file, then import this file to whatever place you're trying to use `containerKey.globalPaintBounds`. – vovahost Sep 30 '20 at 10:26
3

I changed @vovahost extension function, because it's not working in transformed widgets(for example widgets inside RotatedBox). This is working on all widgets.

extension GlobalKeyExtension on GlobalKey {
  Rect? get globalPaintBounds {
    final renderObject = currentContext?.findRenderObject();
    final matrix = renderObject?.getTransformTo(null);

    if (matrix != null && renderObject?.paintBounds != null) {
      final rect = MatrixUtils.transformRect(matrix, renderObject!.paintBounds);
      return rect;
    } else {
      return null;
    }
  }
}
Karen Hovhannisyan
  • 1,020
  • 2
  • 19
  • 29
2

Maybe this simple widget is what you want : rect_getter 0.0.1

This is a widget provide a simple way to get child's rectangle information after rendered.

demo

debuggerx
  • 41
  • 3