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

Posted

技术标签:

【中文标题】Flutter,如何获取小部件的大小?【英文标题】:Flutter, How to get the size of a widget? 【发布时间】:2019-07-11 00:34:38 【问题描述】:

我遇到了这个示例来获取小部件的大小/位置: 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,
                    )
                  ],
                ),
              )
            ],
          ),
        );
      
    

【问题讨论】:

【参考方案1】:

您可以在 LayoutBuilder 中进行包装:

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

【讨论】:

【参考方案2】:

这是因为_keyRed 未附加到代码中的上下文。

修复它-

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

【讨论】:

我现在明白了。密钥所需的任何小部件的大小/位置都可以在其构造函数中传递给它。谢谢 我已经在使用全局键来显示快餐栏弹出窗口。最终 GlobalKey _scaffoldKey = new GlobalKey();我如何将 2 个全局键传递给脚手架来解决此问题 这不是返回 Scaffold 的大小/位置吗?除非我误解了,否则我怀疑 Hamza 下面的答案实际上是正确的。【参考方案3】:

在您提到的链接中,创建 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,
                 ),
         ),

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

以上是关于Flutter,如何获取小部件的大小?的主要内容,如果未能解决你的问题,请参考以下文章

在 Flutter 测试中获取小部件的位置?

如何测试 Flutter 小部件的固有大小

Flutter - 如何在我的未来构建器文本小部件中获得价值回报

Flutter 如何将小部件扩展为具有更多内容的更大小部件?

如何在 Flutter 中使用 Provider 正确获取 API

如何在 Flutter 小部件测试中等待未来完成?