[译]Flutter: Widget Size and Position

栏目: Android · 发布时间: 6年前

内容简介:我遇到过很多人问,如何在屏幕上获取Widgets 的 size 和 position 的问题。在某些情况下,我们会发现我们总是会有一些原因需要去实现这个功能。但是 Widget本身是没有 size 和 position。为了实现这一点,我们必须获得与Widget上下文相关联的RenderBox。我们可以创建一个demo,在Column中画3个不同颜色的面板,分别是红、紫、绿,再在底部写两个按钮分别是 Get Sizes, Get Position.

原文链接 作者: Diego Velasquez 喜欢理由:可以更好的调试布局问题

[译]Flutter: Widget Size and Position

我遇到过很多人问,如何在屏幕上获取Widgets 的 size 和 position 的问题。在某些情况下,我们会发现我们总是会有一些原因需要去实现这个功能。但是 Widget本身是没有 size 和 position。为了实现这一点,我们必须获得与Widget上下文相关联的RenderBox。

How do we do this?

我们可以创建一个demo,在Column中画3个不同颜色的面板,分别是红、紫、绿,再在底部写两个按钮分别是 Get Sizes, Get Position.

demo 代码片段

_getSizes() {
   }

   _getPositions(){
   }

  @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 and Position

现在的问题是:我如何得到每个面板的 size 和 position?

让我们先关注上面的红面板,当我们知道如何获取它的 size 和 position,那么对于其他面板也就迎刃而解了。

获取 Widget 的 Size

为了实现这个,我们需要让我们的Widget有一个Key,所以我们要创建一个GlobalKey并赋值给我们的Widget

//creating Key for red panel
GlobalKey _keyRed = GlobalKey();
...
//set key
    Flexible(
             flex: 2,
             child: Container(
               key: _keyRed,
               color: Colors.red,
             ),
     ),
复制代码

一旦我们Widget 有了 Key,我们就能通过下面的方式根据Key去获取size。

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

如果我们点击 Get Sizes 按钮,在控制台将显示

flutter: SIZE of Red: Size(375.0, 152.9)
复制代码

现在我们知道 红色面板的宽高分别是 375.0 152.9

很简单对吧,让我们继续获取Widget所处的位置信息

获取Widget的位置

与之前的方式一样,我们的Widget必须有一个Key值,我们更新一下获取Widget位置的方法,来获取Widget 相对于定义位置左上角的位置(在这个例子中,我们使用 0.0来表示当前屏幕的左上角)

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

如果点击 Get Positions 按钮,将在控制台打印出:

flutter: POSITION of Red: Offset(0.0, 76.0)
复制代码

这说明我们的Widget 在X轴上是0.0 在Y轴上是76.0(在屏幕的左上角)

为什么是76.0?那是因为在这个例子中上面有个高度为76.0的AppBar

[译]Flutter: Widget Size and Position

哇~ 到这里,我们已经知道如何去获取Widget的 size 和 position

But~ 如果我想在开始的时候就得到 size 和 position,而不是通过按钮的的点击获取,该如何?

[译]Flutter: Widget Size and Position

那么试试在构造函数中调用我们的方法

_MainSizeAndPositionState(){
     _getSizes();
     _getPositions();
   }
复制代码

运行一下demo,会出现错误信息

flutter: The following NoSuchMethodError was thrown building Builder:
flutter: The method 'findRenderObject' was called on null.
flutter: Receiver: null
flutter: Tried calling: findRenderObject()
复制代码

那么我们试试从InitState中调用会怎么样

@override
  void initState() {
    _getSizes();
    _getPositions();
    super.initState();
  }
复制代码

运行一下demo,与刚才有点不一样,但还是报错

flutter: Another exception was thrown: NoSuchMethodError: The method 'findRenderObject' was called on null.
复制代码

那我们要在开始的时候获取大小和位置该如何去做呢?

[译]Flutter: Widget Size and Position

上面报错的原因是因为我们的state还没有得到相应的context。

以下网址可以找到更多的信息关于Widget的生命周期 medium.com/flutter-com… ,掘金上有一篇翻译的,但是作者与来源不一样,内容差不多,可以参考 juejin.im/post/5c768a…

因此我们必须等待Widget完成渲染后,再执行。但是该怎么做?

下面有个简单的实现方式:

@override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
    super.initState();
  }
 _afterLayout(_) {
    _getSizes();
    _getPositions();
  }
复制代码

这样就可以确保布局渲染完成后去调用你的方法

再运行一次demo,将会得到:

flutter: SIZE of Red: Size(375.0, 152.9)
flutter: POSITION of Red: Offset(0.0, 76.0)
复制代码

最后!!!

你也可以回顾一下我朋友 Simon Lightfoot 创建的package pub.dartlang.org/packages/af…

总结

很多次我们都会把简单的事情搞得非常复杂。所以仔细阅读Flutter提供的官方文档其实很有必要,毕竟我们每天都在学习新的东西。

你可以在我的 flutter-samples repo中查看我的源代码 github.com/diegovelope…


以上所述就是小编给大家介绍的《[译]Flutter: Widget Size and Position》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

计算理论导论

计算理论导论

塞普斯 / 机械工业出版社 / 2002-8 / 39.0

This book——by a noted authority and educator in the field——presents computer science theory from a uniquely intuitive,“big picture”perspective.The author grounds his clear and interesting study on ......一起来看看 《计算理论导论》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具