原文连接
做者: Diego Velasquez
喜欢理由:能够更好的调试布局问题html
How do we do this?git
咱们能够建立一个demo,在Column中画3个不一样颜色的面板,分别是红、紫、绿,再在底部写两个按钮分别是 Get Sizes, Get Position.
demo 代码片断github
_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,
)
],
),
)
],
),
);
}
复制代码
效果图: bash
为了实现这个,咱们须要让咱们的Widget有一个Key,因此咱们要建立一个GlobalKey并赋值给咱们的Widgetapp
//creating Key for red panel
GlobalKey _keyRed = GlobalKey();
...
//set key
Flexible(
flex: 2,
child: Container(
key: _keyRed,
color: Colors.red,
),
),
复制代码
一旦咱们Widget 有了 Key,咱们就能经过下面的方式根据Key去获取size。ide
_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必须有一个Key值,咱们更新一下获取Widget位置的方法,来获取Widget 相对于定义位置左上角的位置(在这个例子中,咱们使用 0.0来表示当前屏幕的左上角)post
_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
_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.
复制代码
那咱们要在开始的时候获取大小和位置该如何去作呢?
如下网址能够找到更多的信息关于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…
文章中有些连接须要~~你懂的~
这是我第一篇译文,全靠我的的语感翻译的,欢迎指正~~~