Skip to content

Commit

Permalink
Pass keyboard visibility to the modal sheet page
Browse files Browse the repository at this point in the history
check only min extent

Repaint after keyboard closing
  • Loading branch information
ulusoyca committed Jan 8, 2024
1 parent 9a0b275 commit 69069ed
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,24 @@ import 'package:wolt_modal_sheet/wolt_modal_sheet.dart';
///
/// This widget is responsible for displaying the main content of the scrollable modal sheet.
/// It handles the scroll behavior, page layout, and interactions within the modal sheet.
class WoltModalSheetMainContent extends StatefulWidget {
final ValueNotifier<double> currentScrollPosition;
class WoltModalSheetMainContent extends StatelessWidget {
final ScrollController? scrollController;
final GlobalKey pageTitleKey;
final SliverWoltModalSheetPage page;
final WoltModalType woltModalType;

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

@override
State<WoltModalSheetMainContent> createState() =>
_WoltModalSheetMainContentState();
}

class _WoltModalSheetMainContentState extends State<WoltModalSheetMainContent> {
late ScrollController scrollController;

@override
void initState() {
super.initState();
scrollController = widget.page.scrollController ??
ScrollController(
initialScrollOffset: widget.currentScrollPosition.value);
}

@override
Widget build(BuildContext context) {
final themeData = Theme.of(context).extension<WoltModalSheetThemeData>();
final defaultThemeData = WoltModalSheetDefaultThemeData(context);
final page = widget.page;
final heroImageHeight = page.heroImage == null
? 0.0
: (page.heroImageHeight ??
Expand Down Expand Up @@ -85,7 +68,7 @@ class _WoltModalSheetMainContentState extends State<WoltModalSheetMainContent> {
} else {
final pageTitle = page.pageTitle;
return KeyedSubtree(
key: widget.pageTitleKey,
key: pageTitleKey,
child: pageTitle ?? const SizedBox.shrink(),
);
}
Expand All @@ -101,24 +84,12 @@ class _WoltModalSheetMainContentState extends State<WoltModalSheetMainContent> {
),
],
);
return NotificationListener<ScrollNotification>(
onNotification: (scrollNotification) {
final isVerticalScrollNotification =
scrollNotification is ScrollUpdateNotification &&
scrollNotification.metrics.axis == Axis.vertical;
if (isVerticalScrollNotification) {
widget.currentScrollPosition.value =
scrollNotification.metrics.pixels;
}
return false;
},
child: Padding(
// The scroll view should be padded by the height of the top bar layer if it's always
// visible. Otherwise, over scroll effect will not be visible due to the top bar layer.
padding:
EdgeInsets.only(top: isTopBarLayerAlwaysVisible ? topBarHeight : 0),
child: scrollView,
),
return Padding(
// The scroll view should be padded by the height of the top bar layer if it's always
// visible. Otherwise, over scroll effect will not be visible due to the top bar layer.
padding:
EdgeInsets.only(top: isTopBarLayerAlwaysVisible ? topBarHeight : 0),
child: scrollView,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,30 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:wolt_modal_sheet/src/content/components/main_content/wolt_modal_sheet_top_bar.dart';
import 'package:wolt_modal_sheet/src/theme/wolt_modal_sheet_default_theme_data.dart';
import 'package:wolt_modal_sheet/src/utils/soft_keyboard_closed_event.dart';
import 'package:wolt_modal_sheet/src/utils/wolt_layout_transformation_utils.dart';
import 'package:wolt_modal_sheet/wolt_modal_sheet.dart';

/// `WoltModalSheetTopBarFlow` controls the top bar behavior within the modal sheet page
/// provided by the [WoltModalSheetPage] when `isTopBarLayerAlwaysVisible` is set to true.
/// [WoltModalSheetTopBarFlow] controls the top bar behavior within the modal sheet page
/// provided by the [WoltModalSheetPage] when `isTopBarLayerAlwaysVisible` is set to false.
///
/// It is responsible for the positioning, translation, and opacity of the top bar as the user
/// scrolls through the content. Utilizing the [Flow] widget, it listens to the current scroll
/// position and performs transformations to achieve the desired effects on the top bar, such as
/// fading in/out and translating vertically.
/// position and soft keyboard closing events, then, performs transformations to achieve the
/// desired effects on the top bar, such as fading in/out and translating vertically.
class WoltModalSheetTopBarFlow extends StatelessWidget {
final ValueListenable<double> currentScrollPositionListenable;
final ScrollController scrollController;
final GlobalKey titleKey;
final double topBarTranslationYAmountInPx;
final SliverWoltModalSheetPage page;
final ValueListenable<SoftKeyboardClosedEvent> softKeyboardClosedListenable;

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

Expand All @@ -43,10 +46,10 @@ class WoltModalSheetTopBarFlow extends StatelessWidget {
delegate: _TopBarFlowDelegate(
topBarHeight: topBarHeight,
heroImageHeight: heroImageHeight,
currentScrollPositionListenable: currentScrollPositionListenable,
scrollController: scrollController,
titleKey: titleKey,
topBarTranslationYAmountInPx: topBarTranslationYAmountInPx,
buildContext: context,
softKeyboardClosedListenable: softKeyboardClosedListenable,
),
children: [WoltModalSheetTopBar(page: page)],
);
Expand All @@ -56,21 +59,26 @@ class WoltModalSheetTopBarFlow extends StatelessWidget {
class _TopBarFlowDelegate extends FlowDelegate {
final double topBarHeight;
final double heroImageHeight;
final ValueListenable<double> currentScrollPositionListenable;
final ScrollController scrollController;
final GlobalKey titleKey;
final double topBarTranslationYAmountInPx;
final BuildContext buildContext;
final ValueListenable<SoftKeyboardClosedEvent> softKeyboardClosedListenable;

_TopBarFlowDelegate({
required this.topBarHeight,
required this.heroImageHeight,
required this.currentScrollPositionListenable,
required this.scrollController,
required this.titleKey,
required this.topBarTranslationYAmountInPx,
required this.buildContext,
}) : super(repaint: currentScrollPositionListenable);
required this.softKeyboardClosedListenable,
}) : super(
repaint: Listenable.merge([
scrollController,
softKeyboardClosedListenable,
]),
);

double get currentScrollPosition => currentScrollPositionListenable.value;
double get currentScrollOffset => scrollController.position.pixels;

@override
void paintChildren(FlowPaintingContext context) {
Expand All @@ -86,7 +94,7 @@ class _TopBarFlowDelegate extends FlowDelegate {
WoltLayoutTransformationUtils.calculateTransformationValue(
rangeInPx: 8 + pageTitleHeight,
progressInRangeInPx:
currentScrollPosition - topBarTranslationYAndOpacityStartPoint,
currentScrollOffset - topBarTranslationYAndOpacityStartPoint,
startValue: topBarTranslationYStart,
endValue: topBarTranslationYEnd,
);
Expand All @@ -96,7 +104,7 @@ class _TopBarFlowDelegate extends FlowDelegate {
WoltLayoutTransformationUtils.calculateTransformationValue(
rangeInPx: 8,
progressInRangeInPx:
currentScrollPosition - topBarTranslationYAndOpacityStartPoint,
currentScrollOffset - topBarTranslationYAndOpacityStartPoint,
startValue: 0.0,
endValue: 1.0,
);
Expand All @@ -113,9 +121,11 @@ class _TopBarFlowDelegate extends FlowDelegate {
bool shouldRepaint(covariant _TopBarFlowDelegate oldDelegate) {
return heroImageHeight != oldDelegate.heroImageHeight ||
titleKey != oldDelegate.titleKey ||
currentScrollPosition != oldDelegate.currentScrollPosition ||
currentScrollOffset != oldDelegate.currentScrollOffset ||
topBarTranslationYAmountInPx !=
oldDelegate.topBarTranslationYAmountInPx ||
softKeyboardClosedListenable.value !=
oldDelegate.softKeyboardClosedListenable.value ||
topBarHeight != oldDelegate.topBarHeight;
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:wolt_modal_sheet/src/theme/wolt_modal_sheet_default_theme_data.dart';
import 'package:wolt_modal_sheet/src/utils/soft_keyboard_closed_event.dart';
import 'package:wolt_modal_sheet/src/utils/wolt_layout_transformation_utils.dart';
import 'package:wolt_modal_sheet/wolt_modal_sheet.dart';

/// This class represents the top bar title behavior within a modal sheet page.
/// [WoltModalSheetTopBarTitleFlow] controls the top bar title behavior within the modal sheet page
/// provided by the [WoltModalSheetPage] when `isTopBarLayerAlwaysVisible` is set to false.
///
/// It is responsible for the positioning, translation, and opacity of the top bar title as the user
/// scrolls through the content. Utilizing the [Flow] widget, it listens to the current scroll
/// position and soft keyboard closing events, then, performs transformations to achieve the
/// desired effects on the top bar title, such as fading in/out and translating vertically.
class WoltModalSheetTopBarTitleFlow extends StatelessWidget {
final ValueListenable<double> currentScrollPositionListenable;
final ScrollController scrollController;
final GlobalKey titleKey;
final SliverWoltModalSheetPage page;
final Widget topBarTitle;
final ValueListenable<SoftKeyboardClosedEvent> softKeyboardClosedListenable;

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

Expand All @@ -37,9 +46,9 @@ class WoltModalSheetTopBarTitleFlow extends StatelessWidget {
delegate: _TopBarTitleFlowDelegate(
topBarHeight: topBarHeight,
heroImageHeight: heroImageHeight,
currentScrollPositionListenable: currentScrollPositionListenable,
scrollController: scrollController,
titleKey: titleKey,
buildContext: context,
softKeyboardClosedNotifier: softKeyboardClosedListenable,
),
children: [Center(child: topBarTitle)],
);
Expand All @@ -49,19 +58,24 @@ class WoltModalSheetTopBarTitleFlow extends StatelessWidget {
class _TopBarTitleFlowDelegate extends FlowDelegate {
final double topBarHeight;
final double heroImageHeight;
final ValueListenable<double> currentScrollPositionListenable;
final ScrollController scrollController;
final GlobalKey titleKey;
final BuildContext buildContext;
final ValueListenable<SoftKeyboardClosedEvent> softKeyboardClosedNotifier;

_TopBarTitleFlowDelegate({
required this.topBarHeight,
required this.heroImageHeight,
required this.currentScrollPositionListenable,
required this.scrollController,
required this.titleKey,
required this.buildContext,
}) : super(repaint: currentScrollPositionListenable);
required this.softKeyboardClosedNotifier,
}) : super(
repaint: Listenable.merge([
scrollController,
softKeyboardClosedNotifier,
]),
);

double get currentScrollPosition => currentScrollPositionListenable.value;
double get currentScrollPosition => scrollController.position.pixels;

@override
void paintChildren(FlowPaintingContext context) {
Expand Down Expand Up @@ -108,7 +122,10 @@ class _TopBarTitleFlowDelegate extends FlowDelegate {
bool shouldRepaint(covariant _TopBarTitleFlowDelegate oldDelegate) {
return heroImageHeight != oldDelegate.heroImageHeight ||
titleKey != oldDelegate.titleKey ||
currentScrollPosition != oldDelegate.currentScrollPosition ||
scrollController.position.pixels !=
oldDelegate.scrollController.position.pixels ||
softKeyboardClosedNotifier.value !=
oldDelegate.softKeyboardClosedNotifier.value ||
topBarHeight != oldDelegate.topBarHeight;
}
}
Loading

0 comments on commit 69069ed

Please sign in to comment.