简介
之前咱们介绍了一个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:
@override RenderIndexedStack createRenderObject(BuildContext context) { assert(_debugCheckHasDirectionality(context)); return RenderIndexedStack( index: index, alignment: alignment, textDirection: textDirection ?? Directionality.maybeOf(context), ); } @override void 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办法:
@override void paintStack(PaintingContext context, Offset offset) { if (firstChild == null || index == null) return; final RenderBox child = _childAtIndex(); final StackParentData childParentData = child.parentData! as StackParentData; context.paintChild(child, childParentData.offset + offset); }
能够看到在paintStack办法中,只绘制了和index对应的_childAtIndex这个组件,所以如果index不匹配的话,并不会展现进去。
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; @override State<MyHomePage> createState() => _MyHomePageState();}class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void _changeIndex() { setState(() { _counter = (_counter+1) % 4; print(_counter); }); } @override Widget 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), ), ); }
程序运行之后的成果如下:
通过点击右下方的按钮,咱们失去了不同的widget。
总结
IndexWidget和tab有点相似,大家能够在须要的时候应用。
本文的例子:https://github.com/ddean2009/learn-flutter.git
更多内容请参考 www.flydean.com
最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!
欢送关注我的公众号:「程序那些事」,懂技术,更懂你!