Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Animation Styles for WoltModalSheet by using #165

Merged
merged 2 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,56 @@ Here is an example that shows all the modal sheet elements in use:

![Modal sheet elements in use](https://github.com/woltapp/wolt_modal_sheet/blob/main/doc/bottom_sheet_example.jpeg?raw=true)

## Customizable Animations

Developers can customize the page scrolling and pagination animations by
providing an instance of `WoltModalSheetAnimationStyle` class to
`WoltModalSheetThemeData`.

### Default Animation Style Specifications

#### Pagination Animation

![Modal sheet elements in use](https://github.com/woltapp/wolt_modal_sheet/blob/main/doc/pagination_modal_sheet.png?raw=true)

#### Scrolling Animation

![Modal sheet elements in use](https://github.com/woltapp/wolt_modal_sheet/blob/main/doc/scrolling_modal_sheet.png?raw=true)

### Example Configuration

```dart
WoltModalSheetThemeData(
animationStyle: WoltModalSheetAnimationStyle(
paginationAnimationStyle: WoltModalSheetPaginationAnimationStyle(
mainContentIncomingOpacityCurve: const Interval(
150 / 350,
350 / 350,
curve: Curves.linear,
),
modalSheetHeightTransitionCurve: const Interval(
0 / 350,
300 / 350,
curve: Curves.fastOutSlowIn,
),
incomingSabOpacityCurve: const Interval(
100 / 350,
300 / 350,
curve: Curves.linear,
),
// Define additional pagination animation styles as needed.
),
scrollAnimationStyle: WoltModalSheetScrollAnimationStyle(
heroImageScaleStart: 1.0,
heroImageScaleEnd: 0.9,
topBarTitleTranslationYInPixels: 8.0,
topBarTranslationYInPixels: 4.0,
// Define additional scroll animation styles as needed.
),
),
),
```

## Usage of WoltModalSheet Pages

The WoltModalSheet library provides three primary classes for constructing
Expand Down
Binary file added doc/pagination_modal_sheet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/scrolling_modal_sheet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:wolt_modal_sheet/src/utils/wolt_layout_transformation_utils.dart';
import 'package:wolt_modal_sheet/wolt_modal_sheet.dart';

/// The hero image widget displayed on top of the main content.
///
Expand All @@ -19,6 +20,7 @@ class WoltModalSheetHeroImage extends StatelessWidget {
required this.heroImage,
required this.topBarHeight,
required this.heroImageHeight,
required this.scrollAnimationStyle,
Key? key,
}) : super(key: key);

Expand All @@ -31,13 +33,17 @@ class WoltModalSheetHeroImage extends StatelessWidget {
/// The height of the hero image.
final double heroImageHeight;

/// Animation styles for scrolling within Wolt Modal Sheet Page.
final WoltModalSheetScrollAnimationStyle scrollAnimationStyle;

@override
Widget build(BuildContext context) {
return Flow(
delegate: _HeroImageFlowDelegate(
scrollPosition: Scrollable.of(context).position,
topBarHeight: topBarHeight,
heroImageHeight: heroImageHeight,
scrollAnimationStyle: scrollAnimationStyle,
),
children: [heroImage],
);
Expand All @@ -57,6 +63,7 @@ class _HeroImageFlowDelegate extends FlowDelegate {
required this.scrollPosition,
required this.topBarHeight,
required this.heroImageHeight,
required this.scrollAnimationStyle,
}) : super(repaint: scrollPosition);

/// The scroll position of the modal sheet.
Expand All @@ -68,6 +75,9 @@ class _HeroImageFlowDelegate extends FlowDelegate {
/// The height of the hero image.
final double heroImageHeight;

/// Animation styles for scrolling within Wolt Modal Sheet Page.
final WoltModalSheetScrollAnimationStyle scrollAnimationStyle;

@override
Size getSize(BoxConstraints constraints) {
return super.getSize(constraints.copyWith(maxHeight: heroImageHeight));
Expand All @@ -88,8 +98,8 @@ class _HeroImageFlowDelegate extends FlowDelegate {
// Calculate scale
final double scale =
WoltLayoutTransformationUtils.calculateTransformationValue(
startValue: 1.1,
endValue: 1.0,
startValue: scrollAnimationStyle.heroImageScaleStart,
endValue: scrollAnimationStyle.heroImageScaleEnd,
rangeInPx: heroImageHeight - topBarHeight - 8,
progressInRangeInPx: currentScrollPosition,
);
Expand All @@ -100,8 +110,8 @@ class _HeroImageFlowDelegate extends FlowDelegate {
rangeInPx: (((heroImageHeight - topBarHeight) / 2) - 8),
progressInRangeInPx:
currentScrollPosition - ((heroImageHeight - topBarHeight) / 2),
startValue: 1.0,
endValue: 0.0,
startValue: scrollAnimationStyle.heroImageOpacityStart,
endValue: scrollAnimationStyle.heroImageOpacityEnd,
);

// Calculate the translation to center the image
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ class WoltModalSheetMainContent extends StatelessWidget {
final GlobalKey pageTitleKey;
final SliverWoltModalSheetPage page;
final WoltModalType woltModalType;
final WoltModalSheetScrollAnimationStyle scrollAnimationStyle;

const WoltModalSheetMainContent({
required this.scrollController,
required this.pageTitleKey,
required this.page,
required this.woltModalType,
required this.scrollAnimationStyle,
Key? key,
}) : super(key: key);

Expand Down Expand Up @@ -61,6 +63,7 @@ class WoltModalSheetMainContent extends StatelessWidget {
topBarHeight: topBarHeight,
heroImage: heroImage,
heroImageHeight: heroImageHeight,
scrollAnimationStyle: scrollAnimationStyle,
)
// If top bar layer is always visible, the padding is explicitly added to the
// scroll view since top bar will not be integrated to scroll view at all.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ import 'package:wolt_modal_sheet/wolt_modal_sheet.dart';
class WoltModalSheetTopBarFlow extends StatelessWidget {
final ScrollController scrollController;
final GlobalKey titleKey;
final double topBarTranslationYAmountInPx;
final SliverWoltModalSheetPage page;
final ValueListenable<SoftKeyboardClosedEvent> softKeyboardClosedListenable;
final WoltModalSheetScrollAnimationStyle scrollAnimationStyle;

const WoltModalSheetTopBarFlow({
required this.page,
required this.scrollController,
required this.titleKey,
required this.topBarTranslationYAmountInPx,
required this.softKeyboardClosedListenable,
required this.scrollAnimationStyle,
Key? key,
}) : super(key: key);

Expand All @@ -48,8 +48,8 @@ class WoltModalSheetTopBarFlow extends StatelessWidget {
heroImageHeight: heroImageHeight,
scrollController: scrollController,
titleKey: titleKey,
topBarTranslationYAmountInPx: topBarTranslationYAmountInPx,
softKeyboardClosedListenable: softKeyboardClosedListenable,
scrollAnimationStyle: scrollAnimationStyle,
),
children: [WoltModalSheetTopBar(page: page)],
);
Expand All @@ -61,15 +61,15 @@ class _TopBarFlowDelegate extends FlowDelegate {
final double heroImageHeight;
final ScrollController scrollController;
final GlobalKey titleKey;
final double topBarTranslationYAmountInPx;
final ValueListenable<SoftKeyboardClosedEvent> softKeyboardClosedListenable;
final WoltModalSheetScrollAnimationStyle scrollAnimationStyle;

_TopBarFlowDelegate({
required this.topBarHeight,
required this.heroImageHeight,
required this.scrollController,
required this.titleKey,
required this.topBarTranslationYAmountInPx,
required this.scrollAnimationStyle,
required this.softKeyboardClosedListenable,
}) : super(
repaint: Listenable.merge([
Expand All @@ -84,7 +84,8 @@ class _TopBarFlowDelegate extends FlowDelegate {
void paintChildren(FlowPaintingContext context) {
final pageTitleHeight = titleKey.currentContext!.size!.height;

final topBarTranslationYStart = -1 * topBarTranslationYAmountInPx;
final topBarTranslationYStart =
-1 * scrollAnimationStyle.topBarTranslationYInPixels;
const topBarTranslationYEnd = 0.0;
final topBarTranslationYAndOpacityStartPoint =
heroImageHeight == 0 ? 0 : heroImageHeight - topBarHeight - 8;
Expand All @@ -105,8 +106,8 @@ class _TopBarFlowDelegate extends FlowDelegate {
rangeInPx: 8,
progressInRangeInPx:
currentScrollOffset - topBarTranslationYAndOpacityStartPoint,
startValue: 0.0,
endValue: 1.0,
startValue: scrollAnimationStyle.topBarOpacityStart,
endValue: scrollAnimationStyle.topBarOpacityEnd,
);

/// Paint Top Bar
Expand All @@ -122,8 +123,6 @@ class _TopBarFlowDelegate extends FlowDelegate {
return heroImageHeight != oldDelegate.heroImageHeight ||
titleKey != oldDelegate.titleKey ||
currentScrollOffset != oldDelegate.currentScrollOffset ||
topBarTranslationYAmountInPx !=
oldDelegate.topBarTranslationYAmountInPx ||
softKeyboardClosedListenable.value !=
oldDelegate.softKeyboardClosedListenable.value ||
topBarHeight != oldDelegate.topBarHeight;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ class WoltModalSheetTopBarTitleFlow extends StatelessWidget {
final SliverWoltModalSheetPage page;
final Widget topBarTitle;
final ValueListenable<SoftKeyboardClosedEvent> softKeyboardClosedListenable;
final WoltModalSheetScrollAnimationStyle scrollAnimationStyle;

const WoltModalSheetTopBarTitleFlow({
required this.page,
required this.scrollController,
required this.titleKey,
required this.topBarTitle,
required this.softKeyboardClosedListenable,
required this.scrollAnimationStyle,
Key? key,
}) : super(key: key);

static const _topBarTitleTranslationYAmount = 8.0;

@override
Widget build(BuildContext context) {
final themeData = Theme.of(context).extension<WoltModalSheetThemeData>();
Expand All @@ -49,6 +49,7 @@ class WoltModalSheetTopBarTitleFlow extends StatelessWidget {
scrollController: scrollController,
titleKey: titleKey,
softKeyboardClosedNotifier: softKeyboardClosedListenable,
scrollAnimationStyle: scrollAnimationStyle,
),
children: [Center(child: topBarTitle)],
);
Expand All @@ -61,13 +62,15 @@ class _TopBarTitleFlowDelegate extends FlowDelegate {
final ScrollController scrollController;
final GlobalKey titleKey;
final ValueListenable<SoftKeyboardClosedEvent> softKeyboardClosedNotifier;
final WoltModalSheetScrollAnimationStyle scrollAnimationStyle;

_TopBarTitleFlowDelegate({
required this.topBarHeight,
required this.heroImageHeight,
required this.scrollController,
required this.titleKey,
required this.softKeyboardClosedNotifier,
required this.scrollAnimationStyle,
}) : super(
repaint: Listenable.merge([
scrollController,
Expand All @@ -80,11 +83,10 @@ class _TopBarTitleFlowDelegate extends FlowDelegate {
@override
void paintChildren(FlowPaintingContext context) {
final double pageTitleHeight = titleKey.currentContext!.size!.height;
const topBarTitleTranslationYStart =
-1 * WoltModalSheetTopBarTitleFlow._topBarTitleTranslationYAmount;
const topBarTitleTranslationYAmount =
WoltModalSheetTopBarTitleFlow._topBarTitleTranslationYAmount;
const topBarTitleTranslationYEnd =
final topBarTitleTranslationYAmount =
scrollAnimationStyle.topBarTitleTranslationYInPixels;
final topBarTitleTranslationYStart = -1 * topBarTitleTranslationYAmount;
final topBarTitleTranslationYEnd =
topBarTitleTranslationYStart + topBarTitleTranslationYAmount;

final topBarTitleTranslationYAndOpacityStartPoint =
Expand All @@ -106,8 +108,8 @@ class _TopBarTitleFlowDelegate extends FlowDelegate {
rangeInPx: pageTitleHeight / 2,
progressInRangeInPx:
currentScrollPosition - topBarTitleTranslationYAndOpacityStartPoint,
startValue: 0.0,
endValue: 1.0,
startValue: scrollAnimationStyle.topBarTitleOpacityStart,
endValue: scrollAnimationStyle.topBarTitleOpacityEnd,
);

/// Paint Top Bar Title
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:wolt_modal_sheet/src/content/components/paginating_group/wolt_modal_sheet_page_transition_state.dart';
import 'package:wolt_modal_sheet/wolt_modal_sheet.dart';

class MainContentAnimatedBuilder extends StatefulWidget {
final AnimationController controller;
Expand All @@ -9,6 +10,7 @@ class MainContentAnimatedBuilder extends StatefulWidget {
final bool forwardMove;
final double sheetWidth;
final WoltModalSheetPageTransitionState pageTransitionState;
final WoltModalSheetPaginationAnimationStyle paginationAnimationStyle;

const MainContentAnimatedBuilder({
required this.controller,
Expand All @@ -18,6 +20,7 @@ class MainContentAnimatedBuilder extends StatefulWidget {
required this.forwardMove,
required this.sheetWidth,
required this.pageTransitionState,
required this.paginationAnimationStyle,
super.key,
});

Expand All @@ -41,8 +44,9 @@ class _MainContentAnimatedBuilderState
if (_sizeFactor == null &&
incomingContext?.mounted == true &&
outgoingContext?.mounted == true) {
_sizeFactor = widget.pageTransitionState.mainContentSizeFactor(
_sizeFactor = widget.pageTransitionState.mainContentHeightTransition(
widget.controller,
widget.paginationAnimationStyle,
incomingMainContentHeight: incomingContext!.size!.height,
outgoingMainContentHeight: outgoingContext!.size!.height,
);
Expand All @@ -63,10 +67,13 @@ class _MainContentAnimatedBuilderState
sizeFactor: _sizeFactor ??
pageTransitionState.defaultMainContentSizeFactor(controller),
child: Opacity(
opacity: pageTransitionState.mainContentOpacity(controller).value,
opacity: pageTransitionState
.mainContentOpacity(controller, widget.paginationAnimationStyle)
.value,
child: SlideTransition(
position: pageTransitionState.mainContentSlidePosition(
controller,
widget.paginationAnimationStyle,
sheetWidth: widget.sheetWidth,
screenWidth: screenWidth,
isForwardMove: widget.forwardMove,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
import 'package:flutter/material.dart';
import 'package:wolt_modal_sheet/wolt_modal_sheet.dart';

import 'wolt_modal_sheet_page_transition_state.dart';

class NavigationToolbarAnimatedBuilder extends StatelessWidget {
final AnimationController controller;
final Widget child;
final WoltModalSheetPageTransitionState pageTransitionState;
final WoltModalSheetPaginationAnimationStyle paginationAnimationStyle;

const NavigationToolbarAnimatedBuilder({
required this.pageTransitionState,
required this.controller,
required this.child,
required this.paginationAnimationStyle,
super.key,
});

@override
Widget build(BuildContext context) {
final opacity = pageTransitionState.navigationToolbarOpacity(controller);
final opacity = pageTransitionState.navigationToolbarOpacity(
controller,
paginationAnimationStyle,
);
return AnimatedBuilder(
animation: controller,
builder: (BuildContext _, __) {
Expand Down
Loading
Loading