shimmer_effect.dart 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import 'package:flutter/material.dart';
  2. class ShimmerEffect extends StatefulWidget {
  3. final Widget child;
  4. final Duration duration; // 控制光线滑动的速度
  5. final List<Color> colors; // 渐变的颜色列表 与 stops 配合使用,长度必须一致
  6. final Alignment begin; // 光线起点
  7. final Alignment end; // 光线终点
  8. final double shimmerWidth; // 光线宽度参数
  9. final Duration delay; // 每次执行完后的延迟时间
  10. const ShimmerEffect({
  11. super.key,
  12. required this.child,
  13. this.duration = const Duration(seconds: 2),
  14. this.colors = const [
  15. Colors.transparent,
  16. Colors.white38,
  17. Colors.transparent,
  18. ],
  19. this.begin = const Alignment(-1, -1),
  20. this.end = const Alignment(1, 1),
  21. this.shimmerWidth = 0.1,
  22. this.delay = const Duration(seconds: 1),
  23. });
  24. @override
  25. _ShimmerEffectState createState() => _ShimmerEffectState();
  26. }
  27. class _ShimmerEffectState extends State<ShimmerEffect>
  28. with SingleTickerProviderStateMixin {
  29. late AnimationController _controller;
  30. @override
  31. void initState() {
  32. super.initState();
  33. // 初始化动画控制器
  34. _controller = AnimationController(
  35. vsync: this,
  36. duration: widget.duration,
  37. );
  38. _startAnimation();
  39. }
  40. void _startAnimation() async {
  41. while (mounted) {
  42. await _controller.forward();
  43. _controller.reset();
  44. await Future.delayed(widget.delay);
  45. }
  46. }
  47. @override
  48. void dispose() {
  49. _controller.dispose();
  50. super.dispose();
  51. }
  52. @override
  53. Widget build(BuildContext context) {
  54. return AnimatedBuilder(
  55. animation: _controller,
  56. builder: (context, child) {
  57. final shimmerPosition = _controller.value * 2 - 1;
  58. return ClipRRect(
  59. borderRadius: BorderRadius.circular(8),
  60. child: ShaderMask(
  61. shaderCallback: (bounds) {
  62. return LinearGradient(
  63. begin: widget.begin,
  64. end: widget.end,
  65. colors: widget.colors,
  66. stops: [
  67. shimmerPosition - widget.shimmerWidth,
  68. shimmerPosition,
  69. shimmerPosition + widget.shimmerWidth,
  70. ],
  71. ).createShader(bounds);
  72. },
  73. blendMode: BlendMode.screen,
  74. child: widget.child,
  75. ));
  76. },
  77. child: widget.child,
  78. );
  79. }
  80. }