lazy_load_indexed_stack.dart 1.7 KB

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