<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
我們在開發web應用的時候,有時候為了適應瀏覽器大小的調整,需要動態對頁面的元件進行位置的調整。這時候就會用到flow layout,也就是流式佈局。
同樣的,在flutter中也有流式佈局,這個流式佈局的名字叫做Flow。事實上,在flutter中,Flow通常是和FlowDelegate一起使用的,FlowDelegate用來設定Flow子元件的大小和位置,通過使用FlowDelegate.paintChildre可以更加高效的進行子widget的重繪操作。今天我們來詳細講解flutter中flow的使用。
先來看下Flow的定義:
class Flow extends MultiChildRenderObjectWidget
Flow繼承自MultiChildRenderObjectWidget,說它裡面可以包含多個子widget。
再來看下它的建構函式:
Flow({ Key? key, required this.delegate, List<Widget> children = const <Widget>[], this.clipBehavior = Clip.hardEdge, }) : assert(delegate != null), assert(clipBehavior != null), super(key: key, children: RepaintBoundary.wrapAll(children));
可以看到Flow中主要有三個屬性,分別是delegate,children和clipBehavior。
children很好理解了,它就是Flow中的子元素。
clipBehavior是一個Clip型別的變數,表示的是如何對widget進行裁剪。這裡的預設值是none。
最後一個非常重要的屬性就是FlowDelegate,FlowDelegate主要用來控制Flow中子widget的位置變換。所以,當我們在Flow中定義好子widget之後,剩下的就是定義FlowDelegate來控制如何展示這些子widget。
FlowDelegate是一個抽象類,所以我們在使用的時候,需要繼承它。
FlowDelegate有幾個非常重要的方法:
Size getSize(BoxConstraints constraints) => constraints.biggest;
這個方法用來定義Flow的size,對於Flow來說,它的size是和子widget的size是獨立的,Flow的大小通過getSize方法來定義。
接下來是getConstraintsForChild方法:
BoxConstraints getConstraintsForChild(int i, BoxConstraints constraints) => constraints;
getConstraintsForChild用來控制子widget的Constraints。
paintChildren用來控制如何繪製子widget,也是我們必須要實現的方法:
void paintChildren(FlowPaintingContext context);
FlowDelegate還有兩個方法,分別用來判斷是否需要Relayout和Repaint,這兩個方法的引數都是FlowDelegate:
bool shouldRelayout(covariant FlowDelegate oldDelegate) => false; bool shouldRepaint(covariant FlowDelegate oldDelegate);
有了上面的介紹,我們基本上已經瞭解如何構建Flow了,接下來我們通過一個具體的例子來加深對Flow的理解。
在本例中,我們主要是使用Flow來排列幾個圖示。
首先我們定義一個圖示的陣列:
final List<IconData> buttonItems = <IconData>[ Icons.home, Icons.ac_unit, Icons.adb, Icons.airplanemode_active, Icons.account_box_rounded, ];
然後通過每個圖示對應的IconData來構建一個IconButton的widget:
Widget flowButtonItem(IconData icon) { return Padding( padding: const EdgeInsets.symmetric(vertical: 10.0), child: IconButton( icon: Icon(icon, size: 50, color: Colors.blue ), onPressed: () { buttonAnimation.status == AnimationStatus.completed ? buttonAnimation.reverse() : buttonAnimation.forward(); }, ) ); }
這裡我們使用的是IconButton,為了在不同IconButton之間留一些空間,我們將IconButton封裝在Padding中。
在onPressed方法中,我們希望能夠處理一些動畫效果。這裡的buttonAnimation是一個AnimationController物件:
AnimationController buttonAnimation = AnimationController( duration: const Duration(milliseconds: 250), vsync: this, );
有了flowButtonItem之後,我們就可以構建Flow了:
Widget build(BuildContext context) { return Flow( delegate: FlowButtonDelegate(buttonAnimation: buttonAnimation), children: buttonItems.map<Widget>((IconData icon) => flowButtonItem(icon)).toList(), ); }
Flow的child就是我們剛剛建立的flowButtonItem,FlowButtonDelegate是我們需要新建的類,因為之前在構建flowButtonItem的時候,我們希望進行一些動畫的繪製,而FlowDelegate又是真正用來控制子Widget繪製的類,所以我們需要將buttonAnimation作為引數傳遞給FlowButtonDelegate。
下面是FlowButtonDelegate的定義:
class FlowButtonDelegate extends FlowDelegate { FlowButtonDelegate({required this.buttonAnimation}) : super(repaint: buttonAnimation); final Animation<double> buttonAnimation; @override bool shouldRepaint(FlowButtonDelegate oldDelegate) { return buttonAnimation != oldDelegate.buttonAnimation; } @override void paintChildren(FlowPaintingContext context) { double dy = 0.0; for (int i = 0; i < context.childCount; ++i) { dy = context.getChildSize(i)!.height * i; context.paintChild( i, transform: Matrix4.translationValues( 0, dy * buttonAnimation.value, 0, ), ); } }
FlowButtonDelegate繼承自FlowDelegate,並且傳入了buttonAnimation物件。
這裡我們根據buttonAnimation是否發生變化來決定是否進行Repaint。
如果需要進行Repaint,那麼就要呼叫paintChildren的方法。
在paintChildren中,我們根據child自身的height和buttonAnimation的值來進行動畫的繪製。
那麼buttonAnimation的值是如何變化的呢?這就要回顧之前我們建立flowButtonItems的onPress方法了。
在onPress方法中,我們呼叫了buttonAnimation.reverse或者buttonAnimation.forward這兩個方法來修改buttonAnimation的值。
執行之後的效果如下:
初始狀態下,所有的元件都是在一起的。
當我們點選上面的圖示的時候,我們可以得到下面的介面:
圖示在動畫中展開了。
Flow是一種比較複雜的layout元件,如果和動畫進行結合使用,可以得到非常完美的效果。
本文的例子:github.com/ddean2009/l…
以上就是flutter中使用流式佈局範例詳解的詳細內容,更多關於flutter 流式佈局的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45