2017-09-01 66 views
4

我在Flutter中已經遇到了幾次相當大的障礙。 動畫或構建小部件,這取決於其他小部件以獲得其大小/位置。根據另一個小部件的位置/大小來定位/調整小部件

幾個例子可能是我最糟糕的噩夢: 動態顯示彼此相鄰的小部件。 在CSS中,我們不得不這樣:

.root { 
 
    display: flex; 
 
    background: grey; 
 
    padding: 4px; 
 
} 
 
.root > div { 
 
    background: lightgrey; 
 
    margin-right: 5px; 
 
    padding: 5px; 
 
}
<div class="root"> 
 
    <div> 
 
     dynamic height 
 
     <br/> 
 
     dynamic width 
 
     <br/> 
 
     fat 
 
     <br/> 
 
     super fat 
 
    </div> 
 
    <div> 
 
     dynamic width 
 
     <br/> 
 
     dynamic height 
 
    </div> 
 
</div>

  • 父採用全寬(並不重要)。
  • 父母需要最大的孩子的高度。
  • 兒童用較小的高度拉伸以適應父
  • 兒童positionned緊挨彼此

在顫,我不認爲我們可以同時把所有的4分。

現在如果我們有2個這樣的列表和一個元素從一個列表移動到另一個列表的動畫呢? 例如

enter image description hereenter image description here

又如。如果我們想要一個SlideTransition完成與另一個沒有任何共同點的小部件垂直對齊,該怎麼辦? 像這樣:

enter image description here

這些是完全隨機的例子。我不需要重現完全一樣的東西。 這裏真正的問題是:是否有通用方式做類似的事情(獲取屏幕大小/位置)?有些東西會而不是是特定於這個用例,並且以後會很容易維護嗎?

回答

1

要回答您的原始佈局問題,您可以使用IntrinsicHeight小工具和CrossAxisAlignment.stretch一起完成此佈局。它看起來像這樣:

screenshot

下面的代碼:

import 'package:flutter/material.dart'; 

void main() { 
    runApp(new MyApp()); 
} 

class MyApp extends StatelessWidget { 
    @override 
    Widget build(BuildContext context) { 
    return new MaterialApp(
     home: new MyHomePage(), 
    ); 
    } 
} 

class MyHomePage extends StatelessWidget { 
    @override 
    Widget build(BuildContext context) { 
    return new Scaffold(
     body: new Padding(
     padding: new EdgeInsets.all(10.0), 
     child: new IntrinsicHeight(
      child: new Container(
      color: Colors.grey, 
      padding: new EdgeInsets.all(4.0), 
      child: new Row(
       mainAxisAlignment: MainAxisAlignment.start, 
       crossAxisAlignment: CrossAxisAlignment.stretch, 
       children: <Widget>[ 
       new Container(
        padding: new EdgeInsets.all(5.0), 
        margin: new EdgeInsets.only(right: 5.0), 
        color: Colors.grey[200], 
        child: new Column(
        crossAxisAlignment: CrossAxisAlignment.start, 
        children: <Widget>[ 
         new Text('dynamic height'), 
         new Text('dynamic width'), 
         new Text('fat'), 
         new Text('super fat'), 
        ], 
       ), 
       ), 
       new Container(
        padding: new EdgeInsets.all(5.0), 
        color: Colors.grey[200], 
        child: new Column(
        crossAxisAlignment: CrossAxisAlignment.start, 
        children: <Widget>[ 
         new Text('dynamic width'), 
         new Text('dynamic height'), 
        ], 
       ), 
       ), 
       ], 
      ), 
     ), 
     ), 
    ), 
    ); 
    } 
} 

要實現你的更先進的動畫的例子,我會建議使用CustomMultiChildLayout來定位框。見畫廊的animation demo使用這個類的一個先進的動畫例如:

screenshot

+0

阿涼,不知道你可以使用'IntrinsicHeight'這樣。另一方面,對於我展示的動畫,「CustomChildLayout」將不起作用。不僅CustomChildLayout的大小不能在子節點上放置;但它仍然無法解決訪問全球小部件的世界位置/大小的問題。 – Darky

+0

你在問很多問題,我想你應該考慮把它們分解成自己的Stack Overflow問題。如果你使用'MultiChildLayoutDelegate',你的小部件的大小將在'performLayout'中提供給你。你可以通過調用'layoutChild'來確定你的孩子的大小。如果你想獲得'renderObject'的全局座標,你可以使用['localToGlobal'](https://docs.flutter.io/flutter/rendering/RenderBox/localToGlobal.html),但如果你這樣做, '可能違反了封裝並且應該在更高級別實現自定義佈局 –

+0

請注意,對於簡單的使用情況,您可以使用'LayoutBuilder'來獲取圍繞窗口小部件的大小約束。不過,如果你實現'MultiChildLayoutDelegate',你不需要這個。 –