Skip to content

Commit

Permalink
feat(player): animated gradient background
Browse files Browse the repository at this point in the history
  • Loading branch information
KRTirtho committed Apr 7, 2023
1 parent 80959aa commit 49b5d0e
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 149 deletions.
21 changes: 13 additions & 8 deletions lib/components/player/player_controls.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,18 @@ class PlayerControls extends HookConsumerWidget {
minimumSize: const Size(28, 28),
);

final accentColor = palette?.lightVibrantColor ??
palette?.darkVibrantColor ??
dominantColor;

final resumePauseStyle = IconButton.styleFrom(
backgroundColor: accentColor?.color ?? theme.colorScheme.primary,
foregroundColor:
accentColor?.titleTextColor ?? theme.colorScheme.onPrimary,
padding: const EdgeInsets.all(12),
iconSize: 24,
);

return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
Expand Down Expand Up @@ -199,14 +211,7 @@ class PlayerControls extends HookConsumerWidget {
: Icon(
playing ? SpotubeIcons.pause : SpotubeIcons.play,
),
style: IconButton.styleFrom(
backgroundColor:
dominantColor?.color ?? theme.colorScheme.primary,
foregroundColor: dominantColor?.titleTextColor ??
theme.colorScheme.onPrimary,
padding: const EdgeInsets.all(12),
iconSize: 24,
),
style: resumePauseStyle,
onPressed: Actions.handler<PlayPauseIntent>(
context,
PlayPauseIntent(ref),
Expand Down
127 changes: 127 additions & 0 deletions lib/components/shared/animated_gradient.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

class AnimateGradient extends HookWidget {
const AnimateGradient({
Key? key,
required this.primaryColors,
required this.secondaryColors,
this.child,
this.primaryBegin,
this.primaryEnd,
this.secondaryBegin,
this.secondaryEnd,
AnimationController? controller,
this.duration = const Duration(seconds: 4),
this.animateAlignments = true,
this.reverse = true,
}) : assert(primaryColors.length >= 2),
assert(primaryColors.length == secondaryColors.length),
_controller = controller,
super(key: key);

/// [controller]: pass this to have a fine control over the [Animation]
final AnimationController? _controller;

/// [duration]: Time to switch between [Gradient].
/// By default its value is [Duration(seconds:4)]
final Duration duration;

/// [primaryColors]: These will be the starting colors of the [Animation].
final List<Color> primaryColors;

/// [secondaryColors]: These Colors are those in which the [primaryColors] will transition into.
final List<Color> secondaryColors;

/// [primaryBegin]: This is begin [Alignment] for [primaryColors].
/// By default its value is [Alignment.topLeft]
final Alignment? primaryBegin;

/// [primaryBegin]: This is end [Alignment] for [primaryColors].
/// By default its value is [Alignment.topRight]
final Alignment? primaryEnd;

/// [secondaryBegin]: This is begin [Alignment] for [secondaryColors].
/// By default its value is [Alignment.bottomLeft]
final Alignment? secondaryBegin;

/// [secondaryEnd]: This is end [Alignment] for [secondaryColors].
/// By default its value is [Alignment.bottomRight]
final Alignment? secondaryEnd;

/// [animateAlignments]: set to false if you don't want to animate the alignments.
/// This can provide you way cooler animations
final bool animateAlignments;

/// [reverse]: set it to false if you don't want to reverse the animation.
/// using that it will go into one direction only
final bool reverse;

final Widget? child;

@override
Widget build(BuildContext context) {
// ignore: no_leading_underscores_for_local_identifiers
final __controller = useAnimationController(
duration: duration,
)..repeat(reverse: reverse);

final controller = _controller ?? __controller;

final animation = useMemoized(
() => CurvedAnimation(
parent: controller,
curve: Curves.easeInOut,
),
[controller]);

final colorTween = useMemoized(
() => primaryColors.map((color) {
return ColorTween(
begin: color,
end: color,
);
}).toList(),
[primaryColors]);
final colors = useMemoized(
() => colorTween.map((color) {
return color.evaluate(animation)!;
}).toList(),
[colorTween, animation]);

final begin = useMemoized(
() => AlignmentTween(
begin: primaryBegin ?? Alignment.topLeft,
end: primaryEnd ?? Alignment.topRight,
),
[primaryBegin, primaryEnd]);

final end = useMemoized(
() => AlignmentTween(
begin: secondaryBegin ?? Alignment.bottomLeft,
end: secondaryEnd ?? Alignment.bottomRight,
),
[secondaryBegin, secondaryEnd]);

return AnimatedBuilder(
animation: animation,
child: child,
builder: (BuildContext context, Widget? child) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: animateAlignments
? begin.evaluate(animation)
: (primaryBegin as Alignment),
end: animateAlignments
? end.evaluate(animation)
: primaryEnd as Alignment,
colors: colors,
),
),
child: child,
);
},
);
}
}
6 changes: 6 additions & 0 deletions lib/components/shared/image/universal_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ class UniversalImage extends HookWidget {
final double? width;
final double scale;
final String? placeholder;
final BoxFit? fit;
const UniversalImage({
required this.path,
this.height,
this.width,
this.placeholder,
this.fit,
this.scale = 1,
Key? key,
}) : super(key: key);
Expand Down Expand Up @@ -57,6 +59,7 @@ class UniversalImage extends HookWidget {
height: height,
width: width,
placeholder: AssetImage(placeholder ?? Assets.placeholder.path),
fit: fit,
);
} else if (Uri.tryParse(path) != null && !path.startsWith("assets")) {
return Image.file(
Expand All @@ -66,6 +69,7 @@ class UniversalImage extends HookWidget {
cacheHeight: height?.toInt(),
cacheWidth: width?.toInt(),
scale: scale,
fit: fit,
errorBuilder: (context, error, stackTrace) {
return Image.asset(
placeholder ?? Assets.placeholder.path,
Expand All @@ -85,6 +89,7 @@ class UniversalImage extends HookWidget {
cacheHeight: height?.toInt(),
cacheWidth: width?.toInt(),
scale: scale,
fit: fit,
errorBuilder: (context, error, stackTrace) {
return Image.asset(
placeholder ?? Assets.placeholder.path,
Expand All @@ -105,6 +110,7 @@ class UniversalImage extends HookWidget {
cacheHeight: height?.toInt(),
cacheWidth: width?.toInt(),
scale: scale,
fit: fit,
errorBuilder: (context, error, stackTrace) {
return Image.asset(
placeholder ?? Assets.placeholder.path,
Expand Down
11 changes: 0 additions & 11 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,6 @@ void main(List<String> rawArgs) async {
enableApplicationParameters: false,
),
FileHandler(await getLogsPath(), printLogs: false),
SnackbarHandler(
const Duration(seconds: 5),
action: SnackBarAction(
label: "Dismiss",
onPressed: () {
ScaffoldMessenger.of(
Catcher.navigatorKey!.currentContext!,
).hideCurrentSnackBar();
},
),
),
],
),
releaseConfig: CatcherOptions(SilentReportMode(), [
Expand Down

0 comments on commit 49b5d0e

Please sign in to comment.