Flutter,如何获取小部件的大小?

问题描述 投票:0回答:5

我遇到这个例子来获取小部件的大小/位置: https://medium.com/@diegoveloper/flutter-widget-size-and-position-b0a9ffed9407

我的代码有什么问题?

我得到错误:

The following NoSuchMethodError was thrown while handling a gesture:
I/flutter ( 8566): The method 'findRenderObject' was called on null.
I/flutter ( 8566): Receiver: null
I/flutter ( 8566): Tried calling: findRenderObject()
void main() {
      runApp(new MyApp());
    }

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(home: MyWidgetSizeTMP());
      }
    }

    class MyWidgetSizeTMP extends StatefulWidget{
      @override
      MyWidgetSizeTMPState createState() {
        return new MyWidgetSizeTMPState();
      }
    }

    class MyWidgetSizeTMPState extends State<MyWidgetSizeTMP> {

      //creating Key for red panel
      GlobalKey _keyRed = GlobalKey();

      _getSizes() {
        final RenderBox renderBoxRed = _keyRed.currentContext.findRenderObject();
        final sizeRed = renderBoxRed.size;
        print("SIZE of Red: $sizeRed");
      }

      _getPositions() {
        final RenderBox renderBoxRed = _keyRed.currentContext.findRenderObject();
        final positionRed = renderBoxRed.localToGlobal(Offset.zero);
        print("POSITION of Red: $positionRed ");
      }

      _afterLayout(_) {
        _getSizes();
        _getPositions();
      }

      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
      }

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
          ),
          body: Column(
            children: <Widget>[
              Flexible(
                flex: 2,
                child: Container(
                  color: Colors.red,
                ),
              ),
              Flexible(
                flex: 1,
                child: Container(
                  color: Colors.purple,
                ),
              ),
              Flexible(
                flex: 3,
                child: Container(
                  color: Colors.green,
                ),
              ),
              Spacer(),
              Padding(
                padding: const EdgeInsets.only(bottom: 8.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    MaterialButton(
                      elevation: 5.0,
                      padding: EdgeInsets.all(15.0),
                      color: Colors.grey,
                      child: Text("Get Sizes"),
                      onPressed: _getSizes,
                    ),
                    MaterialButton(
                      elevation: 5.0,
                      color: Colors.grey,
                      padding: EdgeInsets.all(15.0),
                      child: Text("Get Positions"),
                      onPressed: _getPositions,
                    )
                  ],
                ),
              )
            ],
          ),
        );
      }
    }
flutter widget size
5个回答
16
投票

你可以在 LayoutBuilder 中包装:

return LayoutBuilder(
    builder: (BuildContext context, BoxConstraints constraints) {
//      height: constraints.maxHeight,
//      width: constraints.maxWidth
        return YourWidget();
    }
);

7
投票

这是因为

_keyRed
没有附加到代码中的上下文。

修复它-

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _keyRed,  //Add this.
      appBar: AppBar(

2
投票

在您提到的链接中,创建GlobalKey后,它被分配给red容器

但是在您的代码中您还没有将它分配给容器,因此可以从 _getSizes()_getPositions() 中引用它,_keyRed 在使用之前必须附加到代码中的上下文它。

//creating Key for red panel
GlobalKey _keyRed = GlobalKey();
    ...
    //set key
        Flexible(
                 flex: 2,
                 child: Container(
                   key: _keyRed, // assigned as a key of the red container.
                   color: Colors.red,
                 ),
         ),

1
投票

使用 RenderBox 获取当前小部件的大小。阅读 RenderBox 可以为您提供的所有属性。

获取高度的代码:

class _YourWidgetState extends State<YourWidget> {
  // Remember to assign this key to a widget.
  late final GlobalKey _key = GlobalKey();

  ...

  Widget build(BuildContext context) {
     var renderBox = null;
     if (_key.currentContext?.findRenderObject() != null) {
        renderBox = _key.currentContext!.findRenderObject() as RenderBox;
     }

     final height = renderBox?.size.height;

     ...

     return SomeWidget(
        key: _key,
        ...
     )
  }
}

来自findRenderObject的注意事项:

  • “此方法只会在构建阶段完成后返回有效结果。因此,从构建方法中调用此方法是无效的。它应该只从交互事件处理程序(例如手势回调)或布局或绘制回调中调用.如果State.mounted返回false,调用也是无效的。”
  • “调用这个方法在理论上相对昂贵(在树的深度为 O(N)),但实际上通常很便宜,因为树通常有很多渲染对象,因此到最近的渲染对象的距离通常很短。 “这意味着我的代码可以改进,因为每次调用
    findRenderObject()
    时都会调用
    build()

0
投票

没有直接的方法来计算小部件的大小,所以要找到我们必须借助小部件的上下文。

调用 context.size 返回 Size 对象,其中包含小部件的高度和宽度。 context.size 计算小部件的渲染框并返回大小。

结帐https://medium.com/flutterworld/flutter-how-to-get-the-height-of-the-widget-be4892abb1a2

© www.soinside.com 2019 - 2024. All rights reserved.