写点什么

flutter 系列之:flutter 中的 IndexedStack

作者:程序那些事
  • 2022 年 6 月 21 日
  • 本文字数:2360 字

    阅读完需:约 8 分钟

简介

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

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

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

发布于: 刚刚阅读数: 3
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
flutter系列之:flutter中的IndexedStack_flutter_程序那些事_InfoQ写作社区