flutter系列之:flutter中可以建索引的棧布局IndexedStack

目錄

  • 簡介
  • IndexedStack簡介
  • IndexedStack的使用
  • 總結
簡介之前我們介紹了一個flutter的棧結構的layout組件叫做Stack,通過Stack我們可以將一些widget疊放在其他widget之上,從而可以實現圖像的組合功能,也是日常中最常用的一種組件了 。今天我們要介紹的組件是Stack的近親,叫做IndexedStack,它有什么功能呢?一起來看看吧 。
IndexedStack簡介從名字可以看出,IndexedStack是給Stack添加了一個index的功能,事實是否如此呢?我們先來看一下IndexedStack的定義:
class IndexedStack extends Stack可以看到IndexedStack繼承自Stack , 它實際上是Stack的子類,所以之前介紹的Stack有的功能IndexedStack全都有,并且IndexedStack是對Stack的功能進行了增強 。
我們來看下它的構造函數:
IndexedStack({Key? key,AlignmentGeometry alignment = AlignmentDirectional.topStart,TextDirection? textDirection,StackFit sizing = StackFit.loose,this.index = 0,List<Widget> children = const <Widget>[],}) : super(key: key, alignment: alignment, textDirection: textDirection, fit: sizing, children: children);可以看到和Stack相比,IndexedStack多了一個index參數,但是這個參數并沒有傳入到super的構造函數中去,那么index到底是在哪里使用的呢?
別急,IndexedStack還重寫了下面的兩個方法,分別是createRenderObject和updateRenderObject:
@overrideRenderIndexedStack createRenderObject(BuildContext context) {assert(_debugCheckHasDirectionality(context));return RenderIndexedStack(index: index,alignment: alignment,textDirection: textDirection ?? Directionality.maybeOf(context),);}@overridevoid updateRenderObject(BuildContext context, RenderIndexedStack renderObject) {assert(_debugCheckHasDirectionality(context));renderObject..index = index..alignment = alignment..textDirection = textDirection ?? Directionality.maybeOf(context);}和Stack相比,IndexedStack在這兩個方法中使用的是RenderIndexedStack,而Stack使用的是RenderStack 。
所以雖然IndexedStack繼承自Stack,但是兩者在表現上是有本質區別的 。
對于Stack來說,一個widget被放在另外一個widget之上,但是多個widget可以同時展示出來 。而對于IndexedStack來說,它只會展示對應index的widget 。
RenderIndexedStack也是繼承自RenderStack:
class RenderIndexedStack extends RenderStack我們看下它的paintStack方法:
@overridevoid paintStack(PaintingContext context, Offset offset) {if (firstChild == null || index == null)return;final RenderBox child = _childAtIndex();final StackParentData childParentData = https://www.huyubaike.com/biancheng/child.parentData! as StackParentData;context.paintChild(child, childParentData.offset + offset);}可以看到在paintStack方法中,只繪制了和index對應的_childAtIndex這個組件,所以如果index不匹配的話 , 并不會展示出來 。
【flutter系列之:flutter中可以建索引的棧布局IndexedStack】IndexedStack的表現有點像我們常見的tab 。
IndexedStack的使用從上面IndexedStack的構造函數中,我們知道IndexedStack需要傳入一個index屬性和對應的children 。
在本例中,我們給IndexedStack傳入一個可變的index屬性,和4個child:
IndexedStack(index: _counter,children: [widgetOne(),widgetTwo(),widgetThree(),widgetFour(),],)_counter是定義在StatefulWidget中的變量 ??梢酝ㄟ^調用setState方法對index進行修改,從而實現動態切換child的目的 。
這里的child widget很簡單 , 我們使用了不同大小的SizedBox,SizedBox中設置不同的color來方便觀察切換的效果:
Widget widgetOne() {return SizedBox(width: 100,height: 100,child: Container(color: Colors.yellow,),);}最后,在Scaffold的floatingActionButton中調用_changeIndex方法實現index的改變,最終的代碼如下:
class MyHomePage extends StatefulWidget {const MyHomePage({Key? key, required this.title}) : super(key: key);final String title;@overrideState<MyHomePage> createState() => _MyHomePageState();}class _MyHomePageState extends State<MyHomePage> {int _counter = 0;void _changeIndex() {setState(() {_counter = (_counter+1) % 4;print(_counter);});}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(widget.title),),body: Center(child: IndexedStack(index: _counter,children: [widgetOne(),widgetTwo(),widgetThree(),widgetFour(),],),),floatingActionButton: FloatingActionButton(onPressed: _changeIndex,tooltip: 'change index',child: const Icon(Icons.arrow_back),),);}程序運行之后的效果如下:
flutter系列之:flutter中可以建索引的棧布局IndexedStack

推薦閱讀