[译]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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

加密与解密(第4版)

加密与解密(第4版)

段钢 / 电子工业出版社 / 2018-10-1 / 198

《加密与解密(第4版)》以加密与解密为切入点,讲述了软件安全领域的基础知识和技能,如调试技能、逆向分析、加密保护、外壳开发、虚拟机设计等。这些知识彼此联系,读者在掌握这些内容之后,很容易就能在漏洞分析、安全编程、病毒分析、软件保护等领域进行扩展。从就业的角度来说,掌握加密与解密的相关技术,可以提高自身的竞争能力;从个人成长的角度来说,研究软件安全技术有助于掌握一些系统底层知识,是提升职业技能的重要......一起来看看 《加密与解密(第4版)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

SHA 加密
SHA 加密

SHA 加密工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具