Skip to content

Commit

Permalink
Redesign enter exit animation specs
Browse files Browse the repository at this point in the history
  • Loading branch information
ulusoyca committed Jun 30, 2024
1 parent 09943fb commit 7834083
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 49 deletions.
47 changes: 44 additions & 3 deletions lib/src/modal_type/wolt_alert_dialog_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,54 @@ class WoltAlertDialogType extends WoltDialogType {
} else {
width = availableWidth - padding; // adjust for very small screens
}
final height = availableSize.height * 0.8;

return BoxConstraints(
minWidth: width,
maxWidth: width,
minHeight: height,
maxHeight: height,
minHeight: 0,
maxHeight: availableSize.height * 0.8,
);
}

/// Defines a transition animation for the alert dialog's appearance.
///
/// [context] is the build context.
/// [animation] is the primary animation controller for the dialog's appearance.
/// [secondaryAnimation] manages the coordination with other routes' transitions.
/// [child] is the content widget to be animated.
///
/// Returns a transition widget that manages the dialog's transition animation.
@override
Widget buildTransitions(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
final alphaAnimation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(
parent: animation,
curve: const Interval(0.0, 100.0 / 300.0, curve: Curves.linear),
reverseCurve: const Interval(100.0 / 250.0, 1.0, curve: Curves.linear),
));

final scaleAnimation = Tween<double>(
begin: 0.6,
end: 1.0,
).animate(CurvedAnimation(
parent: animation,
curve: const Cubic(0.2, 0.6, 0.4, 1.0), // Cubic for enter
reverseCurve: const Cubic(0.5, 0, 0.7, 0.2), // Cubic for exit
));

return ScaleTransition(
scale: scaleAnimation,
child: FadeTransition(
opacity: alphaAnimation,
child: child,
),
);
}
}
26 changes: 15 additions & 11 deletions lib/src/modal_type/wolt_bottom_sheet_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ class WoltBottomSheetType extends WoltModalType {
showDragHandle: showDragHandle,
);

static const Duration _defaultEnterDuration = Duration(milliseconds: 250);
static const Duration _defaultExitDuration = Duration(milliseconds: 200);
static const Duration _defaultEnterDuration = Duration(milliseconds: 350);
static const Duration _defaultExitDuration = Duration(milliseconds: 250);
static const ShapeBorder _defaultShapeBorder = RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(16.0)),
);
Expand Down Expand Up @@ -125,9 +125,7 @@ class WoltBottomSheetType extends WoltModalType {
)
: modal;

/// Defines the animation for the modal's appearance with a vertical slide transition.
///
/// This method customizes how the modal enters the screen, emphasizing a smooth and natural motion from the bottom to the top.
/// Defines the animation for the modal's appearance.
///
/// [context] is the build context.
/// [animation] is the primary animation controller for the modal's appearance.
Expand All @@ -142,13 +140,19 @@ class WoltBottomSheetType extends WoltModalType {
Animation<double> secondaryAnimation,
Widget child,
) {
return SlideTransition(
position: animation.drive(
Tween(
begin: const Offset(0.0, 1.0),
end: Offset.zero,
).chain(CurveTween(curve: Curves.ease)),
final positionAnimation = Tween<Offset>(
begin: const Offset(0.0, 1.0),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: animation,
curve: const Cubic(0.1, 0.8, 0.2, 1.0), // Cubic for enter
reverseCurve: const Cubic(0.5, 0, 0.7, 0.2), // Cubic for exit
),
);

return SlideTransition(
position: positionAnimation,
child: child,
);
}
Expand Down
17 changes: 10 additions & 7 deletions lib/src/modal_type/wolt_dialog_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,6 @@ class WoltDialogType extends WoltModalType {

/// Defines a transition animation for the dialog's appearance.
///
/// This method customizes how the dialog enters the screen, using animation to smoothly
/// transition.
///
/// [context] is the build context.
/// [animation] is the primary animation controller for the dialog's appearance.
/// [secondaryAnimation] manages the coordination with other routes' transitions.
Expand All @@ -108,11 +105,17 @@ class WoltDialogType extends WoltModalType {
Animation<double> secondaryAnimation,
Widget child,
) {
final alphaAnimation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(
parent: animation,
curve: const Interval(0.0, 100.0 / 300.0, curve: Curves.linear),
reverseCurve: const Interval(100.0 / 250.0, 1.0, curve: Curves.linear),
));

return FadeTransition(
opacity: CurvedAnimation(
parent: animation,
curve: Curves.linear,
),
opacity: alphaAnimation,
child: child,
);
}
Expand Down
1 change: 1 addition & 0 deletions lib/src/modal_type/wolt_modal_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:wolt_modal_sheet/src/modal_type/wolt_modal_dismiss_direction.dar
import 'package:wolt_modal_sheet/wolt_modal_sheet.dart';

export 'wolt_bottom_sheet_type.dart';
export 'wolt_alert_dialog_type.dart';
export 'wolt_dialog_type.dart';
export 'wolt_side_sheet_type.dart';

Expand Down
38 changes: 27 additions & 11 deletions lib/src/modal_type/wolt_side_sheet_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class WoltSideSheetType extends WoltModalType {
minFlingVelocity: minFlingVelocity,
);

static const Duration _defaultEnterDuration = Duration(milliseconds: 250);
static const Duration _defaultEnterDuration = Duration(milliseconds: 300);
static const Duration _defaultExitDuration = Duration(milliseconds: 250);
static const ShapeBorder _defaultShapeBorder = RoundedRectangleBorder(
borderRadius: BorderRadiusDirectional.only(
Expand Down Expand Up @@ -126,18 +126,34 @@ class WoltSideSheetType extends WoltModalType {
Animation<double> secondaryAnimation,
Widget child,
) {
bool isRtl = Directionality.of(context) == TextDirection.rtl;
Offset beginOffset =
isRtl ? const Offset(-1.0, 0.0) : const Offset(1.0, 0.0);
final isRtl = Directionality.of(context) == TextDirection.rtl;

return SlideTransition(
position: animation.drive(
Tween(
begin: beginOffset,
end: Offset.zero,
).chain(CurveTween(curve: Curves.ease)),
final alphaAnimation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(
parent: animation,
curve: const Interval(0.0, 100.0 / 300.0, curve: Curves.linear),
reverseCurve: const Interval(100.0 / 250.0, 1.0, curve: Curves.linear),
));

final positionAnimation = Tween<Offset>(
begin: isRtl ? const Offset(-1.0, 0.0) : const Offset(1.0, 0.0),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: animation,
curve: const Cubic(0.2, 0.6, 0.4, 1.0), // Cubic for enter
reverseCurve: const Cubic(0.5, 0, 0.7, 0.2), // Cubic for exit
),
);

return FadeTransition(
opacity: alphaAnimation,
child: SlideTransition(
position: positionAnimation,
child: child,
),
child: child,
);
}

Expand Down
40 changes: 40 additions & 0 deletions lib/src/widgets/wolt_animated_modal_barrier.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'package:flutter/material.dart';

class WoltAnimatedModalBarrier extends StatelessWidget {
final AnimationController animationController;
final bool barrierDismissible;
final VoidCallback? onModalDismissedWithBarrierTap;

const WoltAnimatedModalBarrier({
Key? key,
required this.animationController,
required this.barrierDismissible,
this.onModalDismissedWithBarrierTap,
}) : super(key: key);

@override
Widget build(BuildContext context) {
final alphaAnimation = Tween<double>(
begin: 1.0,
end: 0.0,
).animate(CurvedAnimation(
parent: animationController,
curve: const Interval(0.0, 1.0, curve: Curves.linear),
));

return FadeTransition(
opacity: alphaAnimation,
child: ModalBarrier(
semanticsLabel: MaterialLocalizations.of(context).scrimLabel,
dismissible: barrierDismissible,
onDismiss: () {
if (onModalDismissedWithBarrierTap != null) {
onModalDismissedWithBarrierTap!();
} else {
Navigator.of(context).pop();
}
},
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class WoltModalSheetContentGestureDetector extends StatelessWidget {
}

void _handleVerticalDragUpdate(DragUpdateDetails details) {
if (_isDismissUnderway) {
if (_isDismissUnderway || _isDismissed) {
return;
}

Expand All @@ -83,7 +83,7 @@ class WoltModalSheetContentGestureDetector extends StatelessWidget {
}

void _handleVerticalDragEnd(BuildContext context, DragEndDetails details) {
if (_isDismissUnderway) {
if (_isDismissUnderway || _isDismissed) {
return;
}
bool isClosing = false;
Expand Down
21 changes: 6 additions & 15 deletions lib/src/wolt_modal_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:wolt_modal_sheet/src/content/wolt_modal_sheet_animated_switcher.dart';
import 'package:wolt_modal_sheet/src/theme/wolt_modal_sheet_default_theme_data.dart';
import 'package:wolt_modal_sheet/src/utils/wolt_modal_type_utils.dart';
import 'package:wolt_modal_sheet/src/widgets/wolt_animated_modal_barrier.dart';
import 'package:wolt_modal_sheet/src/widgets/wolt_modal_sheet_content_gesture_detector.dart';
import 'package:wolt_modal_sheet/wolt_modal_sheet.dart';

Expand Down Expand Up @@ -355,21 +356,11 @@ class WoltModalSheetState extends State<WoltModalSheet> {
children: [
LayoutId(
id: barrierLayoutId,
child: GestureDetector(
excludeFromSemantics: true,
behavior: HitTestBehavior.opaque,
onTap: () {
if (widget.route.barrierDismissible) {
final onModalDismissedWithBarrierTap =
widget.onModalDismissedWithBarrierTap;
if (onModalDismissedWithBarrierTap != null) {
onModalDismissedWithBarrierTap();
} else {
Navigator.of(context).pop();
}
}
},
child: const SizedBox.expand(),
child: WoltAnimatedModalBarrier(
animationController: widget.route.animationController!,
barrierDismissible: widget.route.barrierDismissible,
onModalDismissedWithBarrierTap:
widget.onModalDismissedWithBarrierTap,
),
),
LayoutId(
Expand Down
8 changes: 8 additions & 0 deletions playground/lib/home/home_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ class _HomeScreenState extends State<HomeScreen> {
: const WoltDialogType().copyWith(
shapeBorder: const BeveledRectangleBorder(),
);
final woltAlertDialogType = _isLightTheme
? const WoltAlertDialogType()
: const WoltDialogType().copyWith(
shapeBorder: const BeveledRectangleBorder(),
);
final bottomSheetType = _isLightTheme
? const WoltBottomSheetType()
: const WoltBottomSheetType().copyWith(
Expand All @@ -148,6 +153,8 @@ class _HomeScreenState extends State<HomeScreen> {
switch (_selectedResponsiveness) {
case _Responsiveness.alwaysDialog:
return woltDialogType;
case _Responsiveness.alwaysAlertDialog:
return woltAlertDialogType;
case _Responsiveness.alwaysBottomSheet:
return bottomSheetType;
case _Responsiveness.alwaysSideSheet:
Expand Down Expand Up @@ -187,6 +194,7 @@ class _HomeScreenState extends State<HomeScreen> {

enum _Responsiveness {
alwaysDialog('Always dialog'),
alwaysAlertDialog('Always alert dialog'),
alwaysBottomSheet('Always bottom sheet'),
alwaysSideSheet('Always side sheet'),
auto('Auto');
Expand Down

0 comments on commit 7834083

Please sign in to comment.