Skip to content

Commit

Permalink
[#16] Create UI for the top snack bar and its animation
Browse files Browse the repository at this point in the history
  • Loading branch information
nmint8m committed Feb 13, 2023
1 parent 5b60152 commit 0e838e3
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 0 deletions.
15 changes: 15 additions & 0 deletions lib/views/common/build_context_ext.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import 'package:flutter/material.dart';
import 'package:kayla_flutter_ic/views/common/loading_indicator/loading_indicator_dialog.dart';
import 'package:kayla_flutter_ic/views/common/top_snack_bar/animated_top_snack_bar.dart';

OverlayEntry? _previousEntry;

extension BuildContextExtension on BuildContext {
void showOrHideLoadingIndicator({
Expand All @@ -16,4 +19,16 @@ extension BuildContextExtension on BuildContext {
Navigator.of(this, rootNavigator: true).pop();
}
}

void showTopSnackBar(Widget child) {
final currentOverlayState = Overlay.of(this);
late OverlayEntry newOverlayState;
newOverlayState =
OverlayEntry(builder: (_) => AnimatedTopSnackBar(child: child));
currentOverlayState.insert(newOverlayState);
if (_previousEntry != null && _previousEntry!.mounted) {
_previousEntry?.remove();
}
_previousEntry = newOverlayState;
}
}
84 changes: 84 additions & 0 deletions lib/views/common/top_snack_bar/animated_top_snack_bar.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:kayla_flutter_ic/utils/durations.dart';

class AnimatedTopSnackBar extends StatefulWidget {
final Widget child;

const AnimatedTopSnackBar({
super.key,
required this.child,
});

@override
AnimatedTopSnackBarState createState() => AnimatedTopSnackBarState();
}

class AnimatedTopSnackBarState extends State<AnimatedTopSnackBar>
with SingleTickerProviderStateMixin {
Timer? _timer;
late final Animation<Offset> _animation;
late final AnimationController _animationController;
final _offsetTween = Tween(begin: const Offset(0, -1), end: Offset.zero);

@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Durations.oneSecond,
reverseDuration: Durations.halfSecond,
);
_animationController.addStatusListener(
(status) {
if (status == AnimationStatus.completed) {
_timer = Timer(Durations.threeSecond, () {
if (mounted) {
_animationController.reverse();
}
});
}
if (status == AnimationStatus.dismissed) {
_timer?.cancel();
}
},
);
_animation = _offsetTween.animate(
CurvedAnimation(
parent: _animationController,
curve: Curves.linearToEaseOut,
reverseCurve: Curves.linearToEaseOut,
),
);
if (mounted) {
_animationController.forward();
}
}

@override
void dispose() {
_animationController.dispose();
_timer?.cancel();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Positioned(
top: 0,
left: 0,
right: 0,
child: SlideTransition(
position: _animation,
child: SafeArea(
top: false,
bottom: false,
left: false,
right: false,
child: widget.child,
),
),
);
}
}
63 changes: 63 additions & 0 deletions lib/views/common/top_snack_bar/top_snack_bar.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:kayla_flutter_ic/gen/assets.gen.dart';

class TopSnackbar extends StatelessWidget {
final String title;
final String message;

const TopSnackbar({
super.key,
required this.title,
required this.message,
});

Widget get _bellImage => SizedBox(
width: 23,
height: 23,
child: Image(
image: Assets.images.icBell.image().image,
fit: BoxFit.cover,
alignment: Alignment.center,
),
);

@override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
color: Colors.black87,
child: SafeArea(
top: true,
left: true,
right: true,
bottom: false,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_bellImage,
const SizedBox(width: 16),
SizedBox(
width: MediaQuery.of(context).size.width - 80,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: Theme.of(context).textTheme.titleSmall,
),
Text(
message,
style: Theme.of(context).textTheme.bodySmall,
),
],
),
),
],
),
),
);
}
}

0 comments on commit 0e838e3

Please sign in to comment.