diff --git a/lib/src/screens/home/content.dart b/lib/src/screens/home/content.dart index 75a4b13..1807865 100644 --- a/lib/src/screens/home/content.dart +++ b/lib/src/screens/home/content.dart @@ -8,9 +8,11 @@ import 'package:furman_now/src/widgets/scroll_view_height.dart'; class HomeContent extends StatefulWidget { final bool collapse; + final ScrollController controller; const HomeContent({ required this.collapse, + required this.controller, Key? key, }) : super(key: key); @@ -19,13 +21,12 @@ class HomeContent extends StatefulWidget { } class _HomeContentState extends State { - final ScrollController _controller = ScrollController(); bool _collapse = false; @override Widget build(BuildContext context) { if (widget.collapse != _collapse) { - _controller.animateTo( + widget.controller.animateTo( 0, duration: const Duration(milliseconds: 400), curve: Curves.easeInOut, @@ -35,7 +36,7 @@ class _HomeContentState extends State { return LayoutBuilder( builder: (context, constraints) => ScrollViewWithHeight( - controller: _controller, + controller: widget.controller, child: Align( alignment: Alignment.bottomCenter, child: TweenAnimationBuilder( @@ -50,7 +51,10 @@ class _HomeContentState extends State { decoration: const BoxDecoration( color: Colors.white, borderRadius: - BorderRadius.vertical(top: Radius.circular(30)), + BorderRadius.vertical( + top: Radius.circular(30), + bottom: Radius.circular(30), + ), ), padding: const EdgeInsets.only(bottom: 15), margin: EdgeInsets.only(top: margin), diff --git a/lib/src/screens/home/home_header.dart b/lib/src/screens/home/home_header.dart index c2960a9..4db71f8 100644 --- a/lib/src/screens/home/home_header.dart +++ b/lib/src/screens/home/home_header.dart @@ -44,6 +44,7 @@ class HomePageHeader extends StatelessWidget { color: Color(0xff26183d), fontSize: 36, fontWeight: FontWeight.w800, + height: 1.2, )), ), ), diff --git a/lib/src/screens/home/index.dart b/lib/src/screens/home/index.dart index 564c789..ecfdd35 100644 --- a/lib/src/screens/home/index.dart +++ b/lib/src/screens/home/index.dart @@ -1,5 +1,6 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:furman_now/src/routes/index.gr.dart'; import 'package:furman_now/src/screens/home/content.dart'; import 'package:furman_now/src/screens/home/state.dart'; @@ -13,75 +14,124 @@ class HomeScreen extends StatefulWidget { } class _HomeScreenState extends State { - bool _collapse = false; + final ScrollController _controller = ScrollController(); + + double overscrollTopAmount = 0; + double overscrollBottomAmount = 0; + + @override + void initState() { + super.initState(); + + _controller.addListener(updateScrollPosition); + } + + updateScrollPosition() { + // bottom overscroll + if (_controller.position.pixels > _controller.position.maxScrollExtent) { + setState(() { + overscrollBottomAmount = + _controller.position.pixels - _controller.position.maxScrollExtent; + }); + } else { + if (overscrollBottomAmount != 0) { + setState(() { + overscrollBottomAmount = 0; + }); + } + } + + // top overscroll + if (_controller.position.pixels < 0) { + setState(() { + overscrollTopAmount = + _controller.position.pixels.abs(); + }); + } else { + if (overscrollTopAmount != 0) { + setState(() { + overscrollTopAmount = 0; + }); + } + } + } + + handleScrollEvent(BuildContext context) { + const scrollMessageSensitivity = 20; + const pageSwitchSensitivity = 60; + var offsetAmount = overscrollTopAmount.abs(); + + if (overscrollTopAmount != 0) { + if (offsetAmount > pageSwitchSensitivity) { + context.router.navigate(const StudentIdRoute()); + context.read().collapse = true; + } else if (offsetAmount > scrollMessageSensitivity) { + context.read().showScrollMessage = true; + } else { + context.read().showScrollMessage = false; + } + } else { + context.read().showScrollMessage = false; + + if (_controller.position.pixels > pageSwitchSensitivity) { + context.router.navigate(const HomeRoute()); + context.read().collapse = false; + } + } + } @override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (context) => HomePageState(), builder: (context, _) => Scaffold( - body: Container( - color: const Color(0xffb7acc9), - child: SafeArea( + body: AnnotatedRegion( + value: SystemUiOverlayStyle.light, child: Container( color: const Color(0xffb7acc9), - child: Stack( - fit: StackFit.loose, - children: [ - const AutoTabsRouter( - routes: [ - HomeRoute(), - StudentIdRoute(), + child: SafeArea( + child: Container( + color: const Color(0xffb7acc9), + child: Stack( + fit: StackFit.loose, + children: [ + // overscroll indicator color + Align( + alignment: Alignment.bottomCenter, + child: Container( + height: overscrollBottomAmount + 30, + color: Colors.grey.shade50, + ), + ), + const AutoTabsRouter( + routes: [ + HomeRoute(), + StudentIdRoute(), + ], + ), + NotificationListener( + onNotification: (notification) { + if (notification is ScrollUpdateNotification) { + handleScrollEvent(context); + } + return true; + }, + child: Consumer( + builder: (context, state, _) => + ClipRect(child: HomeContent( + controller: _controller, + collapse: state.collapse, + ), + ), + ), + ), ], ), - NotificationListener( - onNotification: (notification) { - if (notification is ScrollUpdateNotification) { - final offset = notification.metrics.pixels; - const scrollMessageSensitivity = 20; - const pageSwitchSensitivity = 60; - if (offset < 0) { - var offsetAmount = offset.abs(); - if (offsetAmount > pageSwitchSensitivity) { - context.router.navigate(const StudentIdRoute()); - setState(() { - _collapse = true; - }); - } else if (offsetAmount > scrollMessageSensitivity) { - if (!context.read().showScrollMessage) { - context.read().showScrollMessage = true; - } - } else { - if (context.read().showScrollMessage) { - context.read().showScrollMessage = false; - } - } - } else { - var offsetAmount = offset.abs(); - if (offsetAmount > pageSwitchSensitivity) { - context.router.navigate(const HomeRoute()); - setState(() { - _collapse = false; - }); - } else { - if (context.read().showScrollMessage) { - context.read().showScrollMessage = false; - } - } - } - } - return true; - }, - child: ClipRect(child: HomeContent( - collapse: _collapse, - )), - ), - ], + ), ), ), ), ), - ), ); } } diff --git a/lib/src/screens/home/state.dart b/lib/src/screens/home/state.dart index 5a28f3f..346fc0b 100644 --- a/lib/src/screens/home/state.dart +++ b/lib/src/screens/home/state.dart @@ -2,13 +2,21 @@ import 'package:flutter/material.dart'; class HomePageState extends ChangeNotifier { bool _showScrollMessage = false; + bool _collapse = false; - bool get showScrollMessage { - return _showScrollMessage; + bool get showScrollMessage { return _showScrollMessage; } + set showScrollMessage(bool value) { + if (value != _showScrollMessage) { + _showScrollMessage = value; + notifyListeners(); + } } - set showScrollMessage(bool value) { - _showScrollMessage = value; - notifyListeners(); + bool get collapse { return _collapse; } + set collapse(bool value) { + if (value != _collapse) { + _collapse = value; + notifyListeners(); + } } } \ No newline at end of file diff --git a/lib/src/widgets/home/restaurants/restaurants_list.dart b/lib/src/widgets/home/restaurants/restaurants_list.dart index 8191dca..1b35a03 100644 --- a/lib/src/widgets/home/restaurants/restaurants_list.dart +++ b/lib/src/widgets/home/restaurants/restaurants_list.dart @@ -29,6 +29,7 @@ class _RestaurantsListState extends State { itemCount: restaurants.length, cacheExtent: 10000, scrollDirection: Axis.horizontal, + physics: const BouncingScrollPhysics(), prototypeItem: Padding( padding: const EdgeInsets.only(right: 15), child: RestaurantCard(restaurant: restaurants.first),