Skip to content

Commit

Permalink
Merge pull request #30 from erickzanardo/feat/screen-transitions
Browse files Browse the repository at this point in the history
  • Loading branch information
erickzanardo authored Mar 20, 2023
2 parents 02a7e04 + 0855422 commit 85a8c41
Show file tree
Hide file tree
Showing 15 changed files with 597 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# 0.4.0

- feat: add 'NesConfirmDialog'
- feat: add 'NesFillTransition'
- feat: add 'NesHorizontalCloseTransition'
- feat: add 'NesVerticalCloseTransition'

# 0.3.0

Expand Down
2 changes: 2 additions & 0 deletions example/lib/gallery/gallery_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class GalleryPage extends StatelessWidget {
const SizedBox(height: 32),
const TextSection(),
const SizedBox(height: 32),
const ScreenTransitionsSection(),
const SizedBox(height: 32),
const DialogsSection(),
const SizedBox(height: 32),
const IterableOptionsSection(),
Expand Down
90 changes: 90 additions & 0 deletions example/lib/gallery/sections/screen_transitions.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import 'package:flutter/material.dart';
import 'package:nes_ui/nes_ui.dart';

class ScreenTransitionsSection extends StatelessWidget {
const ScreenTransitionsSection({super.key});

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Screen Transitions',
style: theme.textTheme.displayMedium,
),
const SizedBox(height: 16),
Wrap(
children: [
NesButton(
type: NesButtonType.normal,
child: const Text('Vertical Close'),
onPressed: () {
Navigator.of(context).push(
NesVerticalCloseTransition.route<void>(
pageBuilder: (_, __, ___) {
return _MockPage();
},
),
);
},
),
const SizedBox(width: 16),
NesButton(
type: NesButtonType.normal,
child: const Text('Horizontal Close'),
onPressed: () {
Navigator.of(context).push(
NesHorizontalCloseTransition.route<void>(
pageBuilder: (_, __, ___) {
return _MockPage();
},
),
);
},
),
const SizedBox(width: 16),
NesButton(
type: NesButtonType.normal,
child: const Text('Screen Fill'),
onPressed: () {
Navigator.of(context).push(
NesFillTransition.route<void>(
pageBuilder: (_, __, ___) {
return _MockPage();
},
),
);
},
),
],
),
],
);
}
}

class _MockPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/logo.png'),
const SizedBox(height: 8),
NesButton(
type: NesButtonType.normal,
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('Back'),
),
],
),
),
);
}
}
1 change: 1 addition & 0 deletions example/lib/gallery/sections/sections.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export 'icon_buttons.dart';
export 'icons.dart';
export 'iterable_options.dart';
export 'key_icons.dart';
export 'screen_transitions.dart';
export 'selection_list.dart';
export 'text_fields.dart';
export 'texts.dart';
1 change: 1 addition & 0 deletions lib/src/nes_ui.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export 'controller.dart';
export 'screen_transitions/screen_transitions.dart';
export 'theme.dart';
export 'widgets/widgets.dart';
50 changes: 50 additions & 0 deletions lib/src/screen_transitions/nes_fill.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import 'package:flutter/material.dart';
import 'package:nes_ui/nes_ui.dart';

/// {@nes_fill_transition}
/// A Transition that fills the screen.
/// {@endtemplate}
class NesFillTransition extends NesOverlayTransitionWidget {
/// {@macro nes_fill_transition}
const NesFillTransition({
super.key,
required super.animation,
required super.child,
});

/// Creates a route with this animation.
static PageRouteBuilder<T> route<T>({
required RoutePageBuilder pageBuilder,
}) {
return PageRouteBuilder<T>(
pageBuilder: pageBuilder,
reverseTransitionDuration: const Duration(milliseconds: 750),
transitionDuration: const Duration(milliseconds: 750),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return NesFillTransition(
animation: animation,
child: child,
);
},
);
}

@override
Widget buildOverlay(BuildContext context, double value) {
final overlayTransitionTheme =
context.nesThemeExtension<NesOverlayTransitionTheme>();

final size = MediaQuery.of(context).size;

return Stack(
alignment: Alignment.center,
children: [
Positioned(
width: size.width * value,
height: size.height * value,
child: ColoredBox(color: overlayTransitionTheme.color),
),
],
);
}
}
59 changes: 59 additions & 0 deletions lib/src/screen_transitions/nes_horizontal_close.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import 'package:flutter/material.dart';
import 'package:nes_ui/nes_ui.dart';

/// {@nes_horizontal_close_transition}
/// A Transition that looks like horizontal doors are closing in front
/// of the current screen, opening again with the new one.
/// {@endtemplate}
class NesHorizontalCloseTransition extends NesOverlayTransitionWidget {
/// {@macro nes_horizontal_close_transition}
const NesHorizontalCloseTransition({
super.key,
required super.animation,
required super.child,
});

/// Creates a route with this animation.
static PageRouteBuilder<T> route<T>({
required RoutePageBuilder pageBuilder,
}) {
return PageRouteBuilder<T>(
pageBuilder: pageBuilder,
reverseTransitionDuration: const Duration(milliseconds: 750),
transitionDuration: const Duration(milliseconds: 750),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return NesHorizontalCloseTransition(
animation: animation,
child: child,
);
},
);
}

@override
Widget buildOverlay(BuildContext context, double value) {
final overlayTransitionTheme =
context.nesThemeExtension<NesOverlayTransitionTheme>();
final width = MediaQuery.of(context).size.width;
final half = width / 2;

return Stack(
children: [
Positioned(
top: 0,
bottom: 0,
left: 0,
width: half * value,
child: ColoredBox(color: overlayTransitionTheme.color),
),
Positioned(
top: 0,
bottom: 0,
right: 0,
left: width - (half * value),
child: ColoredBox(color: overlayTransitionTheme.color),
)
],
);
}
}
47 changes: 47 additions & 0 deletions lib/src/screen_transitions/nes_overlay_transition_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'package:flutter/material.dart';

/// {@template nes_overlay_transition_widget}
/// Base widget for all of the Nes UI transition animation.
///
/// It splits the progress of the animation into steps, in order
/// to make it easy to compose the animation.
///
/// {@endtemplate}
abstract class NesOverlayTransitionWidget extends StatelessWidget {
/// {@template nes_overlay_transition_widget}
const NesOverlayTransitionWidget({
required this.animation,
required this.child,
super.key,
});

/// Animation.
final Animation<double> animation;

/// Child.
final Widget child;

@override
Widget build(BuildContext context) {
if (animation.value == 1) {
return child;
}

return Stack(
children: [
if (animation.value >= .5) Positioned.fill(child: child),
if (animation.value <= .5)
Positioned.fill(
child: buildOverlay(context, animation.value * 2),
)
else
Positioned.fill(
child: buildOverlay(context, (1 - animation.value) * 2),
),
],
);
}

/// Returns the widget that will be rendered on top of the screen/child.
Widget buildOverlay(BuildContext context, double value);
}
47 changes: 47 additions & 0 deletions lib/src/screen_transitions/nes_transition_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'package:flutter/material.dart';

/// {@template nes_transition_overlay_widget}
/// Base widget for all of the Nes UI transition animation.
///
/// It splits the progress of the animation into steps, in order
/// to make it easy to compose the animation.
///
/// {@endtemplate}
abstract class NesTransitionOverlayWidget extends StatelessWidget {
/// {@template nes_transition_overlay_widget}
const NesTransitionOverlayWidget({
required this.animation,
required this.child,
super.key,
});

/// Animation.
final Animation<double> animation;

/// Child.
final Widget child;

@override
Widget build(BuildContext context) {
if (animation.value == 1) {
return child;
}

return Stack(
children: [
if (animation.value >= .5) Positioned.fill(child: child),
if (animation.value <= .5)
Positioned.fill(
child: buildOverlay(context, animation.value * 2),
)
else
Positioned.fill(
child: buildOverlay(context, (1 - animation.value) * 2),
),
],
);
}

/// Returns the widget that will be rendered on top of the screen/child.
Widget buildOverlay(BuildContext context, double value);
}
59 changes: 59 additions & 0 deletions lib/src/screen_transitions/nes_vertical_close.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import 'package:flutter/material.dart';
import 'package:nes_ui/nes_ui.dart';

/// {@nes_vertical_close_transition}
/// A Transition that looks like vertical doors are closing in front
/// of the current screen, opening again with the new one.
/// {@endtemplate}
class NesVerticalCloseTransition extends NesOverlayTransitionWidget {
/// {@macro nes_vertical_close_transition}
const NesVerticalCloseTransition({
super.key,
required super.animation,
required super.child,
});

/// Creates a route with this animation.
static PageRouteBuilder<T> route<T>({
required RoutePageBuilder pageBuilder,
}) {
return PageRouteBuilder<T>(
pageBuilder: pageBuilder,
reverseTransitionDuration: const Duration(milliseconds: 750),
transitionDuration: const Duration(milliseconds: 750),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return NesVerticalCloseTransition(
animation: animation,
child: child,
);
},
);
}

@override
Widget buildOverlay(BuildContext context, double value) {
final overlayTransitionTheme =
context.nesThemeExtension<NesOverlayTransitionTheme>();
final height = MediaQuery.of(context).size.height;
final half = height / 2;

return Stack(
children: [
Positioned(
top: 0,
left: 0,
right: 0,
height: half * value,
child: ColoredBox(color: overlayTransitionTheme.color),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
top: height - (half * value),
child: ColoredBox(color: overlayTransitionTheme.color),
)
],
);
}
}
4 changes: 4 additions & 0 deletions lib/src/screen_transitions/screen_transitions.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export 'nes_fill.dart';
export 'nes_horizontal_close.dart';
export 'nes_overlay_transition_widget.dart';
export 'nes_vertical_close.dart';
Loading

0 comments on commit 85a8c41

Please sign in to comment.