简介

之前咱们介绍了一个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

最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!

欢送关注我的公众号:「程序那些事」,懂技术,更懂你!