lazy_load_indexed_stack.dart 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import 'package:flutter/material.dart';
  2. class LazyLoadIndexedStack extends StatefulWidget {
  3. final int index;
  4. final List<WidgetBuilder> children;
  5. const LazyLoadIndexedStack({
  6. super.key,
  7. required this.index,
  8. required this.children,
  9. });
  10. @override
  11. _LazyLoadIndexedStackState createState() => _LazyLoadIndexedStackState();
  12. }
  13. class _LazyLoadIndexedStackState extends State<LazyLoadIndexedStack> {
  14. final Map<int, Widget> _cachedWidgets = {};
  15. @override
  16. Widget build(BuildContext context) {
  17. return Stack(
  18. children: widget.children.asMap().entries.map((entry) {
  19. int i = entry.key;
  20. WidgetBuilder builder = entry.value;
  21. // 如果页面已经加载过,则从缓存中获取
  22. if (!_cachedWidgets.containsKey(i) && i == widget.index) {
  23. _cachedWidgets[i] = builder(context); // 延迟加载
  24. }
  25. // 计算滑动方向
  26. double slideOffset = 0.0;
  27. if (i == widget.index) {
  28. slideOffset = 0.0; // 当前页面居中
  29. } else if (i < widget.index) {
  30. slideOffset = -MediaQuery.of(context).size.width; // 左侧页面
  31. } else {
  32. slideOffset = MediaQuery.of(context).size.width; // 右侧页面
  33. }
  34. return AnimatedPositioned(
  35. duration: const Duration(milliseconds: 300),
  36. curve: Curves.easeInOut,
  37. left: slideOffset,
  38. right: -slideOffset,
  39. top: 0,
  40. bottom: 0,
  41. child: AnimatedOpacity(
  42. duration: const Duration(milliseconds: 200),
  43. opacity: i == widget.index ? 1.0 : 0.0,
  44. child: _cachedWidgets[i] ?? const SizedBox.shrink(),
  45. ),
  46. );
  47. }).toList(),
  48. );
  49. }
  50. }