Flutter中如何获取widget的大小和位置?

本文介绍了在Flutter中如何获取Widget的大小和位置。通过为Widget设置Key,结合RenderBox,可以在事件触发或页面加载时获取Widget的Size和Position。详细展示了在构造函数和initState中获取的错误及解决方案,利用WidgetsBinding的回调确保在Widget渲染完成后再进行获取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在我们实际的开发中,会有要获取某个widget的大小和位置的需求,但是widget本身并没有对应的属性获取size和position,怎么办呢?看官莫急,且往下看。

我们首先创建一个demo工程,长的是这个样子,column中分别有三个不同颜色的widget,底部两个按钮,点击分别获取size和position:
在这里插入图片描述
代码很简单:

	//获取widget大小
    _getSize() {
    }

    //获取widget位置
    _getPosition() {
    }

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        children: <Widget>[
          Flexible(
            flex: 1,
            child: Container(
              color: Colors.red,
            ),
          ),
          Flexible(
            flex: 2,
            child: Container(
              color: Colors.green,
            ),
          ),
          Flexible(
            flex: 1,
            child: Container(
              color: Colors.orange,
            ),
          ),
          Spacer(),
          Padding(
            padding: EdgeInsets.only(bottom: 8.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Expanded(
                  child: MaterialButton(
                    child: Text(
                      "get size!",
                      style: TextStyle(
                        color: Colors.red,
                      ),
                    ),
                    onPressed: _getSize,
                  ),
                ),
                Expanded(
                  child: MaterialButton(
                    child: Text(
                      "get position!",
                      style: TextStyle(
                        color: Colors.red,
                      ),
                    ),
                    onPressed: _getPosition,
                  ),
                )
              ],
            ),
          )
        ],
      ),
    );

OK,回到之前的问题,我们要怎么获取这几个widget的size和position呢?

一、事件触发获取

我们不妨先聚焦到一个widget,比如上面绿色的widget,要想获取widget的size和position,首先需要给这个widget设置一个key:

GlobalKey _keyGreen = GlobalKey();
...
...
Flexible(
   flex: 2,
   child: Container(
   key: _keyGreen,
   color: Colors.green,
   ),
),

一旦为widget设置了key,我们就可以通过key获取到widget对应的RenderBox,从而获取size和position.

获取size:

_getSize() {
    final RenderBox renderBox = _keyGreen.currentContext.findRenderObject();
    final sizeGreen = renderBox.size;
    print("SIZE of green: $sizeGreen");
  }

点击获取size的按钮,会打印如下内容:

flutter: SIZE of green: Size(375.0, 214.0)

这就是我们绿色widget的宽和高。

获取position:

_getPosition() {
    final RenderBox renderBox = _keyGreen.currentContext.findRenderObject();
    final positionGreen = renderBox.localToGlobal(Offset.zero);
    print("POSITION of green: $positionGreen");
  }

同样点击获取position的按钮,打印如下内容:

flutter: POSITION of green: Offset(0.0, 183.0)

这就是绿色widget左上角的坐标,即在整个屏幕中的位置。

二、进入页面获取

以上都是通过点击事件触发的获取size和position,如果需要在进入页面的时候就能获取widget的size和pisition又该如何操作呢?

首先想到的是在类的构造函数或者initState函数中调用我们上面实现的两个方法,然鹅很不幸,尝试过的朋友就会发现,运行报错类似如下:

flutter: Another exception was thrown: NoSuchMethodError: The method ‘findRenderObject’ was called on null.

这是为什么呢?这是因为构造器或者init方法执行的时候,我们的context还没有和state进行关联,此时获取到的currentContext必然是null,获取失败!

等到widget渲染完成后,此时currentContext即widget对应的element就已经和State完成绑定,那我们怎么知道何时widget渲染完毕呢?

其实方法也很简单,WidgetsBinding为我们提供了对应的回调,我们可以这样用:

@override
  initState(){
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) { 
      _afterLayout();
    });
    super.initState();
  }
  
  _afterLayout(){
    _getSize();
    _getPosition();
  }

获取的结果也是没有任何毛病的:

flutter: SIZE of green: Size(375.0, 214.0)
flutter: POSITION of green: Offset(0.0, 183.0)

以上,就是flutter中获取特定widget的size和position的方式,既可以在某个时机获取,也可以进入页面就获取到,非常的方便!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值