初始化

This commit is contained in:
谢宇宁
2026-09-15 15:44:13 +07:00
commit a23ba685e9
1065 changed files with 101122 additions and 0 deletions
@@ -0,0 +1,53 @@
import 'package:flutter/material.dart';
/// 懒加载 + 保活的 IndexedStack(底部 tab 内容页标准写法)
///
/// 没进过的 tab 用空盒占位,首次切到才真正 build;进过一次就一直留在树里,
/// 切走只是不 paintstate / 滚动位置 / 播放器全部保留。
/// 相比 PageView:不需要 AutomaticKeepAlive 保活,也不会预建相邻页。
///
/// 非当前 tab 用 TickerMode(enabled: false) 关掉:IndexedStack 只是不 paint
/// 离屏页的动画/定时器照样在跑(跑马灯、Shimmer、轮播),看不见还空转。
class LazyIndexedStack extends StatefulWidget {
final int index;
final List<Widget> children;
const LazyIndexedStack({super.key, required this.index, required this.children});
@override
State<LazyIndexedStack> createState() => _LazyIndexedStackState();
}
class _LazyIndexedStackState extends State<LazyIndexedStack> {
//已建过的下标:进过一次就永久保活,不再退回占位
final _loaded = <int>{};
@override
void initState() {
super.initState();
_loaded.add(widget.index);
}
@override
void didUpdateWidget(covariant LazyIndexedStack oldWidget) {
super.didUpdateWidget(oldWidget);
_loaded.add(widget.index);
}
@override
Widget build(BuildContext context) {
return IndexedStack(
// 必须 expand:默认的 loose 会让子页拿到非 tight 约束,从而不再是 relayout boundary
// 离屏页一脏就把整个 stack 拖着重新布局(PageView 原来给的是 tight,每页各自隔离)。
// 顺带保证「根节点自身不撑满」的页也能满屏,不依赖各页自觉
sizing: StackFit.expand,
index: widget.index,
children: List.generate(
widget.children.length,
(i) => _loaded.contains(i)
? TickerMode(enabled: i == widget.index, child: widget.children[i])
: const SizedBox.shrink(),
),
);
}
}