原文連接
做者: 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…
文章中有些連接須要~~你懂的~
這是我第一篇譯文,全靠我的的語感翻譯的,歡迎指正~~~