Skip to content

Commit

Permalink
Add AsukaSnackbar
Browse files Browse the repository at this point in the history
Add Solution for Bug Hero animations
  • Loading branch information
Bwolfs2 committed Feb 16, 2021
1 parent ff09a93 commit 9104183
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 53 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"dart.flutterSdkPath": "/Users/jacobmoura/fvm/versions/beta"
"dart.flutterSdkPath": "C:\\Users\\bwolf\\fvm\\versions\\beta"
}
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import 'package:asuka/asuka.dart' as asuka;

MaterialApp(
builder: asuka.builder,
navigatorObservers: [
asuka.asukaHeroController //if u don`t add this Hero will not work
],
);

```
Expand All @@ -36,6 +39,16 @@ asuka.showSnackBar(SnackBar(
content: Text("Hello World"),
));
//some sugar code
AsukaSnackbar.warning("Warning").show();
AsukaSnackbar.success("success").show();
AsukaSnackbar.alert("alert").show();
AsukaSnackbar.info("info").show();
AsukaSnackbar.message("message").show();
```

Expand Down
7 changes: 5 additions & 2 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:example/src/home_page.dart';
import 'package:flutter/material.dart';
import 'package:asuka/asuka.dart' show builder;
import 'package:asuka/asuka.dart' as asuka;

import 'src/second/second_page.dart';

Expand All @@ -17,8 +17,11 @@ class MyApp extends StatelessWidget {
primarySwatch: Colors.red,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
builder: builder,
builder: asuka.builder,
initialRoute: '/',
navigatorObservers: [
asuka.asukaHeroController
],
routes: {
'/': (_) => HomePage(title: 'Asuka'),
'/second': (_) => SecondPage(title: 'Second page'),
Expand Down
52 changes: 51 additions & 1 deletion example/lib/src/home_page.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';

import 'package:asuka/asuka.dart';
import 'home.controller.dart';
import 'second/second_page.dart';

class HomePage extends StatefulWidget {
final String title;
Expand Down Expand Up @@ -28,7 +30,12 @@ class _HomePageState extends State<HomePage> {
RaisedButton(
child: Text('Second Page'),
onPressed: () {
Navigator.pushNamed(context, '/second');
//Navigator.pushNamed(context, '/second');
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondPage(),
));
},
),
SizedBox(height: 10),
Expand All @@ -48,6 +55,49 @@ class _HomePageState extends State<HomePage> {
child: Text('ModalSheet'),
onPressed: homeController.onClickModalSheet,
),
RaisedButton(
child: Text('SnackBar Warning'),
onPressed: () {
AsukaSnackbar.warning("Warning").show();
},
),
RaisedButton(
child: Text('SnackBar Success'),
onPressed: () {
AsukaSnackbar.success("Success").show();
},
),
RaisedButton(
child: Text('SnackBar alert'),
onPressed: () {
AsukaSnackbar.alert("alert").show();
},
),
RaisedButton(
child: Text('SnackBar info'),
onPressed: () {
AsukaSnackbar.info("info").show();
},
),
RaisedButton(
child: Text('SnackBar message'),
onPressed: () {
AsukaSnackbar.message("message").show();
},
),
Row(
children: [
Hero(
tag: "HeroTag",
child: Container(
decoration: BoxDecoration(borderRadius: BorderRadius.circular(100), color: Colors.red),
width: 50,
height: 50,
),
),
],
),
TextField()
],
),
);
Expand Down
8 changes: 7 additions & 1 deletion example/lib/src/second/second_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ class _SecondPageState extends State<SecondPage> {
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Hero(
tag: "HeroTag",
child: Container(
height: 100,
color: Colors.red,
),
),
TextField(),
RaisedButton(
child: Text('Back to Home'),
Expand Down Expand Up @@ -73,7 +80,6 @@ class _SecondPageState extends State<SecondPage> {
onPressed: () {
Navigator.pop(context);
}),

],
),
));
Expand Down
1 change: 1 addition & 0 deletions lib/asuka.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
library asuka;

export 'src/asuka_singleton.dart';
export 'snackbars/asuka_snack_bar.dart';
63 changes: 63 additions & 0 deletions lib/snackbars/asuka_snack_bar.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:asuka/asuka.dart' as asuka;

class AsukaSnackbar extends SnackBar {
AsukaSnackbar._(
Key? key,
String content,
Color background, {
IconData? icon,
SnackBarAction? action,
}) : super(
elevation: 2,
backgroundColor: background,
action: action,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
4,
),
),
behavior: SnackBarBehavior.floating,
content: Row(
children: [
if (icon != null) ...[
Icon(
icon,
size: 20,
color: Colors.black45,
),
SizedBox(width: 10)
],
Expanded(
child: Text(
content,
style: TextStyle(
fontSize: 16,
color: Colors.white,
),
),
),
if (action == null)
InkWell(
child: Icon(Icons.close, color: Colors.white),
onTap: asuka.hideCurrentSnackBar,
)
],
),
);

factory AsukaSnackbar.warning(String content, {Key? key}) => AsukaSnackbar._(key, content, Color(0xFFE6CA72), icon: Icons.warning);

factory AsukaSnackbar.alert(String content, {Key? key}) => AsukaSnackbar._(key, content, Color(0xffFA5456), icon: Icons.report);

factory AsukaSnackbar.info(String content, {Key? key, SnackBarAction? snackBarAction}) => AsukaSnackbar._(key, content, Color(0xff3196DA), action: snackBarAction, icon: Icons.help);

factory AsukaSnackbar.success(String content, {Key? key, SnackBarAction? snackBarAction}) => AsukaSnackbar._(key, content, Color(0xFF80AD49), action: snackBarAction, icon: Icons.check_circle);

factory AsukaSnackbar.message(String content, {Key? key}) => AsukaSnackbar._(key, content, Color(0xff484848));

void call() => show();

void show() => asuka.showSnackBar(this);
}
68 changes: 23 additions & 45 deletions lib/src/asuka_singleton.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import 'package:flutter/material.dart' as material;
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

final _keyScaff = GlobalKey<material.ScaffoldState>();
_ListenerInterface? _dialogs;

void _checkBuilderIsInMaterialApp() {
assert(
_keyScaff.currentState != null, """Add asuka.builder in your MaterialApp;
assert(_keyScaff.currentState != null, """Add asuka.builder in your MaterialApp;
return MaterialApp(
builder: asuka.builder,
Expand All @@ -23,12 +23,10 @@ void _checkBuilderIsInMaterialApp() {
/// It is an error to specify both `above` and `below`.
void addOverlay(OverlayEntry entry, {OverlayEntry? below, OverlayEntry? above}) {
_checkBuilderIsInMaterialApp();
if(_keyScaff.currentContext != null){

OverlayState? overlay = Overlay.of(_keyScaff.currentContext!);
overlay?.insert(entry, below: below, above: above);
if (_keyScaff.currentContext != null) {
OverlayState? overlay = Overlay.of(_keyScaff.currentContext!);
overlay?.insert(entry, below: below, above: above);
}

}

/// Insert all the entries in the given iterable.
Expand All @@ -38,11 +36,9 @@ void addOverlay(OverlayEntry entry, {OverlayEntry? below, OverlayEntry? above})
/// Otherwise, the entries are inserted on top.
///
/// It is an error to specify both `above` and `below`.
void ainsertAllOverlay(Iterable<OverlayEntry> entries,
{OverlayEntry? below, OverlayEntry? above}) {
void ainsertAllOverlay(Iterable<OverlayEntry> entries, {OverlayEntry? below, OverlayEntry? above}) {
_checkBuilderIsInMaterialApp();
Overlay.of(_keyScaff.currentContext!)!
.insertAll(entries, below: below, above: above);
Overlay.of(_keyScaff.currentContext!)!.insertAll(entries, below: below, above: above);
}

/// Shows a [SnackBar] at the bottom of the scaffold.
Expand All @@ -60,31 +56,27 @@ void ainsertAllOverlay(Iterable<OverlayEntry> entries,
/// animation), use [removeCurrentSnackBar].
///
/// See [Scaffold.of] for information about how to obtain the [ScaffoldState].
material.ScaffoldFeatureController<material.SnackBar,
material.SnackBarClosedReason> showSnackBar(material.SnackBar snackbar) {
material.ScaffoldFeatureController<material.SnackBar, material.SnackBarClosedReason> showSnackBar(material.SnackBar snackbar) {
_checkBuilderIsInMaterialApp();
return _keyScaff.currentState!.showSnackBar(snackbar);
return ScaffoldMessenger.of(_keyScaff.currentState!.context).showSnackBar(snackbar);
}

/// Removes the current [SnackBar] (if any) immediately.
///
/// The removed snack bar does not run its normal exit animation. If there are
/// any queued snack bars, they begin their entrance animation immediately.
void removeCurrentSnackBar(
{material.SnackBarClosedReason reason =
material.SnackBarClosedReason.remove}) {
void removeCurrentSnackBar({material.SnackBarClosedReason reason = material.SnackBarClosedReason.remove}) {
_checkBuilderIsInMaterialApp();
return _keyScaff.currentState!.removeCurrentSnackBar(reason: reason);
return ScaffoldMessenger.of(_keyScaff.currentState!.context).removeCurrentSnackBar(reason: reason);
}

/// Removes the current [SnackBar] by running its normal exit animation.
///
/// The closed completer is called after the animation is complete.
void hideCurrentSnackBar(
{material.SnackBarClosedReason reason =
material.SnackBarClosedReason.remove}) {
void hideCurrentSnackBar({material.SnackBarClosedReason reason = material.SnackBarClosedReason.remove}) {
_checkBuilderIsInMaterialApp();
return _keyScaff.currentState!.hideCurrentSnackBar(reason: reason);
//return _keyScaff.currentState!.hideCurrentSnackBar(reason: reason);
return ScaffoldMessenger.of(_keyScaff.currentState!.context).hideCurrentSnackBar(reason: reason);
}

/// Shows a material design bottom sheet in the nearest [Scaffold]. To show
Expand Down Expand Up @@ -113,12 +105,7 @@ void hideCurrentSnackBar(
/// to a menu or a dialog and prevents the user from interacting with the rest
/// of the app. Modal bottom sheets can be created and displayed with the
/// [showModalBottomSheet] function.
material.PersistentBottomSheetController<T> showBottomSheet<T>(
Widget Function(BuildContext) builder,
{Color? backgroundColor,
double? elevation,
ShapeBorder? shape,
Clip? clipBehavior}) {
material.PersistentBottomSheetController<T> showBottomSheet<T>(Widget Function(BuildContext) builder, {Color? backgroundColor, double? elevation, ShapeBorder? shape, Clip? clipBehavior}) {
_checkBuilderIsInMaterialApp();
return _keyScaff.currentState!.showBottomSheet(
builder,
Expand Down Expand Up @@ -182,13 +169,7 @@ material.PersistentBottomSheetController<T> showBottomSheet<T>(
/// * [showCupertinoDialog], which displays an iOS-style dialog.
/// * [showGeneralDialog], which allows for customization of the dialog popup.
/// * <https://material.io/design/components/dialogs.html>
Future<T?> showDialog<T>(
{required WidgetBuilder builder,
bool barrierDismissible = true,
Color? barrierColor,
bool useSafeArea = true,
bool useRootNavigator = true,
RouteSettings? routeSettings}) {
Future<T?> showDialog<T>({required WidgetBuilder builder, bool barrierDismissible = true, Color? barrierColor, bool useSafeArea = true, bool useRootNavigator = true, RouteSettings? routeSettings}) {
_checkBuilderIsInMaterialApp();
return _dialogs!.showDialogListener(
builder: builder,
Expand All @@ -207,14 +188,17 @@ Future<T?> showDialog<T>(
Widget builder(BuildContext context, Widget? child) {
return Navigator(
initialRoute: '/',
observers: [
asukaHeroController
],
onGenerateRoute: (_) => material.MaterialPageRoute(
builder: (context) => _BuildPage(
child: child,
),
builder: (context) => _BuildPage(child: child),
),
);
}

material.HeroController get asukaHeroController => HeroController(createRectTween: (begin, end) => MaterialRectCenterArcTween(begin: begin, end: end));

class _BuildPage extends StatefulWidget {
final Widget? child;
const _BuildPage({Key? key, this.child}) : super(key: key);
Expand All @@ -239,13 +223,7 @@ class __BuildPageState extends State<_BuildPage> implements _ListenerInterface {
}

@override
Future<T?> showDialogListener<T>(
{required WidgetBuilder builder,
bool barrierDismissible = true,
material.Color? barrierColor,
bool useSafeArea = true,
bool useRootNavigator = true,
material.RouteSettings? routeSettings}) {
Future<T?> showDialogListener<T>({required WidgetBuilder builder, bool barrierDismissible = true, material.Color? barrierColor, bool useSafeArea = true, bool useRootNavigator = true, material.RouteSettings? routeSettings}) {
return material.showDialog(
context: context,
builder: builder,
Expand Down
7 changes: 4 additions & 3 deletions test/asuka_test.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:asuka/asuka.dart' as asuka;

void main() {
test('erro when not called build method', () {
expect(() => asuka.showSnackBar(null), throwsAssertionError);
expect(() => asuka.showSnackBar(SnackBar(content: Container())), throwsAssertionError);
expect(() => asuka.hideCurrentSnackBar(), throwsAssertionError);
expect(() => asuka.removeCurrentSnackBar(), throwsAssertionError);
expect(() => asuka.showBottomSheet(null), throwsAssertionError);
expect(() => asuka.showDialog(), throwsAssertionError);
expect(() => asuka.showBottomSheet((e) => Container()), throwsAssertionError);
expect(() => asuka.showDialog(builder: (e) => Container()), throwsAssertionError);
});
}

0 comments on commit 9104183

Please sign in to comment.