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/screens/student_id/index.dart b/lib/src/screens/student_id/index.dart index 766a226..494afe2 100644 --- a/lib/src/screens/student_id/index.dart +++ b/lib/src/screens/student_id/index.dart @@ -7,6 +7,9 @@ import 'package:flutter_remix/flutter_remix.dart'; import 'package:furman_now/src/routes/index.gr.dart'; import 'package:furman_now/src/services/get_app/barcode/barcode_service.dart'; import 'package:furman_now/src/utils/theme.dart'; +import 'package:provider/provider.dart'; + +import '../home/state.dart'; class StudentIdScreen extends StatefulWidget { const StudentIdScreen({Key? key}) : super(key: key); @@ -44,88 +47,94 @@ class _StudentIdScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - body: Listener( - onPointerMove: (details) { - int sensitivity = 8; - if (details.delta.dy > sensitivity) { - // Down Swipe - } else if (details.delta.dy < -sensitivity) { - context.router.navigate(HomeRoute()); - } + body: WillPopScope( + onWillPop: () async { + context.read().collapse = false; + return true; }, - child: Stack( - children: [ - Container( - color: const Color(0xffb7acc9), - child: SafeArea( - child: ListView( - padding: const EdgeInsets.all(40), - children: [ - Text( - "Furman ID", - style: furmanTextStyle(const TextStyle( - color: Color(0xff26183d), - fontSize: 36, - fontWeight: FontWeight.w800 - )), - ), - const SizedBox(height: 30), - Center( - child: Container( - height: 200, - width: 200, - decoration: BoxDecoration( - color: Colors.grey[200], - borderRadius: BorderRadius.circular(40), - ), - child: Icon( - FlutterRemix.user_3_line, - size: 120, - color: Colors.grey[400], + child: Listener( + onPointerMove: (details) { + int sensitivity = 8; + if (details.delta.dy > sensitivity) { + // Down Swipe + } else if (details.delta.dy < -sensitivity) { + context.router.navigate(HomeRoute()); + } + }, + child: Stack( + children: [ + Container( + color: const Color(0xffb7acc9), + child: SafeArea( + child: ListView( + padding: const EdgeInsets.all(40), + children: [ + Text( + "Furman ID", + style: furmanTextStyle(const TextStyle( + color: Color(0xff26183d), + fontSize: 36, + fontWeight: FontWeight.w800 + )), + ), + const SizedBox(height: 30), + Center( + child: Container( + height: 200, + width: 200, + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.circular(40), + ), + child: Icon( + FlutterRemix.user_3_line, + size: 120, + color: Colors.grey[400], + ), ), ), - ), - const SizedBox(height: 20), - Center(child: Text( - "Michael Thomas", - style: furmanTextStyle(const TextStyle( - color: Color(0xff26183d), - fontSize: 28, - fontWeight: FontWeight.w700 + const SizedBox(height: 20), + Center(child: Text( + "Michael Thomas", + style: furmanTextStyle(const TextStyle( + color: Color(0xff26183d), + fontSize: 28, + fontWeight: FontWeight.w700 + )), )), - )), - const SizedBox(height: 5), - Center(child: Text( - "5001962", - style: furmanTextStyle(const TextStyle( - color: Color(0xff26183d), - fontSize: 20, - fontWeight: FontWeight.w500 + const SizedBox(height: 5), + Center(child: Text( + "5001962", + style: furmanTextStyle(const TextStyle( + color: Color(0xff26183d), + fontSize: 20, + fontWeight: FontWeight.w500 + )), )), - )), - const SizedBox(height: 20), - Container( - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(10)), + const SizedBox(height: 20), + Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + // hack since the barcode has a weird intrinsic size for some reason + child: LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return BarcodeWidget( + barcode: Barcode.pdf417(moduleHeight: 4), + data: barcodeNumber, + margin: const EdgeInsets.all(10), + height: constraints.maxWidth / 3, + ); + }, + ), ), - // hack since the barcode has a weird intrinsic size for some reason - child: LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - return BarcodeWidget( - barcode: Barcode.pdf417(moduleHeight: 4), - data: barcodeNumber, - margin: const EdgeInsets.all(10), - height: constraints.maxWidth / 3, - ); - }, - ), - ), - ], + ], + ), ), ), - ), - ], + ], + ), ), ), ); 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),