| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- import 'package:flutter/material.dart';
- class ShimmerEffect extends StatefulWidget {
- final Widget child;
- final Duration duration; // 光效滑动的时间
- final Duration delay; // 每轮动画结束后的延迟
- final Alignment begin; // 滑动起点
- final Alignment end; // 滑动终点
- final ImageProvider image; // 外部传入的光效图片
- final double shimmerWidthFactor; // 光效图片相对于 child 的宽度
- const ShimmerEffect({
- super.key,
- required this.child,
- required this.image,
- this.duration = const Duration(seconds: 2),
- this.delay = const Duration(seconds: 1),
- this.begin = const Alignment(-1, 0),
- this.end = const Alignment(1, 0),
- this.shimmerWidthFactor = 0.2,
- });
- @override
- State<ShimmerEffect> createState() => _ShimmerEffectState();
- }
- class _ShimmerEffectState extends State<ShimmerEffect>
- with SingleTickerProviderStateMixin {
- late final AnimationController _controller;
- late final Animation<double> _animation;
- @override
- void initState() {
- super.initState();
- _controller = AnimationController(
- vsync: this,
- duration: widget.duration,
- );
- _animation = Tween<double>(begin: -1.0, end: 1.0).animate(_controller);
- _startLoop();
- }
- void _startLoop() async {
- while (mounted) {
- await _controller.forward();
- _controller.reset();
- await Future.delayed(widget.delay);
- }
- }
- @override
- void dispose() {
- _controller.dispose();
- super.dispose();
- }
- @override
- Widget build(BuildContext context) {
- return LayoutBuilder(builder: (context, constraints) {
- final width = constraints.maxWidth;
- final shimmerWidth = width * widget.shimmerWidthFactor;
- return Stack(
- children: [
- widget.child,
- AnimatedBuilder(
- animation: _controller,
- builder: (context, _) {
- final dx = _animation.value * (width + shimmerWidth);
- return Positioned(
- left: dx,
- top: 0,
- width: shimmerWidth,
- height: constraints.maxHeight,
- child: IgnorePointer(
- child: Image(
- image: widget.image,
- fit: BoxFit.fill,
- ),
- ),
- );
- },
- )
- ],
- );
- });
- }
- }
|