共计 3328 个字符,预计需要花费 9 分钟才能阅读完成。
简介
之前咱们介绍了一个 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
最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!
欢送关注我的公众号:「程序那些事」, 懂技术,更懂你!