Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/enhancement #23

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 49 additions & 17 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,58 @@ class FullPageShimmerExample extends StatelessWidget {
class ShimmerPage extends StatelessWidget {
const ShimmerPage({super.key});

final _textStyle = const TextStyle(
color: Colors.white,
fontSize: 21.0,
fontWeight: FontWeight.w400
);

@override
Widget build(BuildContext context) {
return Scaffold(
body: Shimmer(
// This is the ONLY required parameter
duration: const Duration(seconds: 3),
// This is NOT the default value. Default value: Duration(seconds: 0)
interval: const Duration(seconds: 5),
// This is the default value
color: Colors.white,
// This is the default value
colorOpacity: 0.3,
// This is the default value
enabled: true,
// This is the default value
direction: const ShimmerDirection.fromLTRB(),
// This is the ONLY required parameter
child: Container(
color: Colors.deepPurple,
),
body: Column(
children: [
Expanded(
child: Shimmer(
// This is the ONLY required parameter
duration: const Duration(seconds: 3),
// This is NOT the default value. Default value: Duration(seconds: 0)
interval: const Duration(milliseconds: 5),
// This is the default value
color: Colors.white,
// This is the default value
colorOpacity: 0.3,
// This is the default value
enabled: true,
// This is the default value
direction: const ShimmerDirection.fromLTRB(),
// This is the ONLY required parameter
child: Container(
color: Colors.deepPurple,
),
)
),
Expanded(
child: Stack(
children: [
Shimmer(
duration: const Duration(seconds: 5),
beginDelay: const Duration(seconds: 2),
mode: ShimmerMode.oneShot,
child: Container(
color: Colors.deepOrange,
),
),
Padding(
padding: const EdgeInsets.all(12.0),
child: Text("mode: ShimmerMode.oneShot\nbeginDelay: const Duration(seconds: 2)",
style: _textStyle,
),
)
],
),
)
],
),
);
}
Expand Down
13 changes: 13 additions & 0 deletions lib/shimmer_animation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ library shimmer_animation;

import 'package:flutter/material.dart';
import 'package:shimmer_animation/src/shimmer_animator.dart';
import 'package:shimmer_animation/src/shimmer_mode.dart';

export 'src/shimmer_mode.dart' show ShimmerMode;

/// Creates simple yet beautiful shimmer animations
///
Expand Down Expand Up @@ -36,17 +39,25 @@ class Shimmer extends StatelessWidget {
/// Accepts a [Duration] that would be the interval between the repeating animation. Default value is [Duration(seconds: 0)] i.e. no interval
final Duration interval;

/// Accepts a [Duration] that would be the delay time to begin animation. Default value is [Duration(seconds: 0)] i.e. no beginDelay
final Duration beginDelay;

/// Accepts a [ShimmerDirection] and aligns the animation accordingly. Default value is [ShimmerDirection.fromLBRT()]
final ShimmerDirection direction;

/// Accepts a [ShimmerMode] that could be set to either one-shot or repeat mode. Default value is [ShimmerMode.repeat]
final ShimmerMode mode;

Shimmer({
required this.child,
this.enabled = true,
this.color = Colors.white,
this.colorOpacity = 0.3,
this.duration = const Duration(seconds: 3),
this.interval = const Duration(seconds: 0),
this.beginDelay = const Duration(seconds: 0),
this.direction = const ShimmerDirection.fromLTRB(),
this.mode = ShimmerMode.repeat
});

@override
Expand All @@ -58,7 +69,9 @@ class Shimmer extends StatelessWidget {
opacity: colorOpacity,
duration: duration,
interval: interval,
beginDelay: beginDelay,
direction: direction,
mode: mode,
);
} else {
return child;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/custom_shimmer_animation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,5 @@ class CustomSplashAnimation extends CustomPainter {
}

@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
bool shouldRepaint(CustomSplashAnimation oldDelegate) => oldDelegate.position != position;
}
36 changes: 25 additions & 11 deletions lib/src/shimmer_animator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:shimmer_animation/shimmer_animation.dart';
import 'package:shimmer_animation/src/custom_shimmer_animation.dart';
import 'package:shimmer_animation/src/shimmer_mode.dart';

class ShimmerAnimator extends StatefulWidget {
final Color color;
final double opacity;
final Duration duration;
final Duration interval;
final Duration beginDelay;
final ShimmerDirection direction;
final ShimmerMode mode;
final Widget child;

ShimmerAnimator({
Expand All @@ -18,7 +21,9 @@ class ShimmerAnimator extends StatefulWidget {
required this.opacity,
required this.duration,
required this.interval,
required this.beginDelay,
required this.direction,
required this.mode,
});

@override
Expand All @@ -31,36 +36,35 @@ class _ShimmerAnimatorState extends State<ShimmerAnimator>
late Animation<double> animation;
late AnimationController controller;
Timer? timer;
late bool isRepeat;

@override
void initState() {
super.initState();
isRepeat = widget.mode == ShimmerMode.repeat;

controller = AnimationController(vsync: this, duration: widget.duration);
animation = Tween<double>(begin: 0, end: 1).animate(CurvedAnimation(
parent: controller,
curve: Interval(0, 0.6, curve: Curves.decelerate),
))
..addListener(() async {
if (controller.isCompleted) {
timer = Timer(widget.interval,
() => mounted ? controller.forward(from: 0) : null);
}
setState(() {});
});
controller.forward();
..addListener(animationEventListener);
Future.delayed(widget.beginDelay, () => controller.forward(),);
}

@override
void dispose() {
controller.dispose();
controller
..removeListener(animationEventListener)
..dispose();
timer?.cancel();
timer = null;
super.dispose();
}

@override
Widget build(BuildContext context) {
return CustomPaint(
return controller.isAnimating ? CustomPaint(
foregroundPainter: CustomSplashAnimation(
context: context,
position: animation.value,
Expand All @@ -70,6 +74,16 @@ class _ShimmerAnimatorState extends State<ShimmerAnimator>
end: widget.direction.end,
),
child: widget.child,
);
) : widget.child;
}

void animationEventListener() {
if (controller.isCompleted) {
if (isRepeat) {
timer = Timer(widget.interval,
() => mounted ? controller.forward(from: 0) : null);
}
}
setState(() {});
}
}
8 changes: 8 additions & 0 deletions lib/src/shimmer_mode.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// [oneShot] Shimmer Effect playing only one.
///
/// [repeat] Shimmer Effect playing continue re-play(default).
///
enum ShimmerMode {
oneShot,
repeat,
}