fix: improve scroll handling on home page to avoid unintentional scroll event detection
This commit is contained in:
		@@ -8,9 +8,11 @@ import 'package:furman_now/src/widgets/scroll_view_height.dart';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class HomeContent extends StatefulWidget {
 | 
					class HomeContent extends StatefulWidget {
 | 
				
			||||||
  final bool collapse;
 | 
					  final bool collapse;
 | 
				
			||||||
 | 
					  final ScrollController controller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const HomeContent({
 | 
					  const HomeContent({
 | 
				
			||||||
    required this.collapse,
 | 
					    required this.collapse,
 | 
				
			||||||
 | 
					    required this.controller,
 | 
				
			||||||
    Key? key,
 | 
					    Key? key,
 | 
				
			||||||
  }) : super(key: key);
 | 
					  }) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -19,13 +21,12 @@ class HomeContent extends StatefulWidget {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _HomeContentState extends State<HomeContent> {
 | 
					class _HomeContentState extends State<HomeContent> {
 | 
				
			||||||
  final ScrollController _controller = ScrollController();
 | 
					 | 
				
			||||||
  bool _collapse = false;
 | 
					  bool _collapse = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    if (widget.collapse != _collapse) {
 | 
					    if (widget.collapse != _collapse) {
 | 
				
			||||||
      _controller.animateTo(
 | 
					      widget.controller.animateTo(
 | 
				
			||||||
        0,
 | 
					        0,
 | 
				
			||||||
        duration: const Duration(milliseconds: 400),
 | 
					        duration: const Duration(milliseconds: 400),
 | 
				
			||||||
        curve: Curves.easeInOut,
 | 
					        curve: Curves.easeInOut,
 | 
				
			||||||
@@ -35,7 +36,7 @@ class _HomeContentState extends State<HomeContent> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return LayoutBuilder(
 | 
					    return LayoutBuilder(
 | 
				
			||||||
      builder: (context, constraints) => ScrollViewWithHeight(
 | 
					      builder: (context, constraints) => ScrollViewWithHeight(
 | 
				
			||||||
        controller: _controller,
 | 
					        controller: widget.controller,
 | 
				
			||||||
        child: Align(
 | 
					        child: Align(
 | 
				
			||||||
          alignment: Alignment.bottomCenter,
 | 
					          alignment: Alignment.bottomCenter,
 | 
				
			||||||
          child: TweenAnimationBuilder<double>(
 | 
					          child: TweenAnimationBuilder<double>(
 | 
				
			||||||
@@ -50,7 +51,10 @@ class _HomeContentState extends State<HomeContent> {
 | 
				
			|||||||
                  decoration: const BoxDecoration(
 | 
					                  decoration: const BoxDecoration(
 | 
				
			||||||
                    color: Colors.white,
 | 
					                    color: Colors.white,
 | 
				
			||||||
                    borderRadius:
 | 
					                    borderRadius:
 | 
				
			||||||
                    BorderRadius.vertical(top: Radius.circular(30)),
 | 
					                      BorderRadius.vertical(
 | 
				
			||||||
 | 
					                        top: Radius.circular(30),
 | 
				
			||||||
 | 
					                        bottom: Radius.circular(30),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                  padding: const EdgeInsets.only(bottom: 15),
 | 
					                  padding: const EdgeInsets.only(bottom: 15),
 | 
				
			||||||
                  margin: EdgeInsets.only(top: margin),
 | 
					                  margin: EdgeInsets.only(top: margin),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,6 +44,7 @@ class HomePageHeader extends StatelessWidget {
 | 
				
			|||||||
                      color: Color(0xff26183d),
 | 
					                      color: Color(0xff26183d),
 | 
				
			||||||
                      fontSize: 36,
 | 
					                      fontSize: 36,
 | 
				
			||||||
                      fontWeight: FontWeight.w800,
 | 
					                      fontWeight: FontWeight.w800,
 | 
				
			||||||
 | 
					                      height: 1.2,
 | 
				
			||||||
                    )),
 | 
					                    )),
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
import 'package:auto_route/auto_route.dart';
 | 
					import 'package:auto_route/auto_route.dart';
 | 
				
			||||||
import 'package:flutter/material.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/routes/index.gr.dart';
 | 
				
			||||||
import 'package:furman_now/src/screens/home/content.dart';
 | 
					import 'package:furman_now/src/screens/home/content.dart';
 | 
				
			||||||
import 'package:furman_now/src/screens/home/state.dart';
 | 
					import 'package:furman_now/src/screens/home/state.dart';
 | 
				
			||||||
@@ -13,14 +14,80 @@ class HomeScreen extends StatefulWidget {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _HomeScreenState extends State<HomeScreen> {
 | 
					class _HomeScreenState extends State<HomeScreen> {
 | 
				
			||||||
  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<HomePageState>().collapse = true;
 | 
				
			||||||
 | 
					      } else if (offsetAmount > scrollMessageSensitivity) {
 | 
				
			||||||
 | 
					        context.read<HomePageState>().showScrollMessage = true;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        context.read<HomePageState>().showScrollMessage = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      context.read<HomePageState>().showScrollMessage = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (_controller.position.pixels > pageSwitchSensitivity) {
 | 
				
			||||||
 | 
					        context.router.navigate(const HomeRoute());
 | 
				
			||||||
 | 
					        context.read<HomePageState>().collapse = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return ChangeNotifierProvider(
 | 
					    return ChangeNotifierProvider(
 | 
				
			||||||
      create: (context) => HomePageState(),
 | 
					      create: (context) => HomePageState(),
 | 
				
			||||||
      builder: (context, _) => Scaffold(
 | 
					      builder: (context, _) => Scaffold(
 | 
				
			||||||
        body: Container(
 | 
					          body: AnnotatedRegion<SystemUiOverlayStyle>(
 | 
				
			||||||
 | 
					            value: SystemUiOverlayStyle.light,
 | 
				
			||||||
 | 
					            child: Container(
 | 
				
			||||||
              color: const Color(0xffb7acc9),
 | 
					              color: const Color(0xffb7acc9),
 | 
				
			||||||
              child: SafeArea(
 | 
					              child: SafeArea(
 | 
				
			||||||
                child: Container(
 | 
					                child: Container(
 | 
				
			||||||
@@ -28,6 +95,14 @@ class _HomeScreenState extends State<HomeScreen> {
 | 
				
			|||||||
                  child: Stack(
 | 
					                  child: Stack(
 | 
				
			||||||
                    fit: StackFit.loose,
 | 
					                    fit: StackFit.loose,
 | 
				
			||||||
                    children: [
 | 
					                    children: [
 | 
				
			||||||
 | 
					                      // overscroll indicator color
 | 
				
			||||||
 | 
					                      Align(
 | 
				
			||||||
 | 
					                        alignment: Alignment.bottomCenter,
 | 
				
			||||||
 | 
					                        child: Container(
 | 
				
			||||||
 | 
					                          height: overscrollBottomAmount + 30,
 | 
				
			||||||
 | 
					                          color: Colors.grey.shade50,
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
                      const AutoTabsRouter(
 | 
					                      const AutoTabsRouter(
 | 
				
			||||||
                        routes: [
 | 
					                        routes: [
 | 
				
			||||||
                          HomeRoute(),
 | 
					                          HomeRoute(),
 | 
				
			||||||
@@ -37,44 +112,18 @@ class _HomeScreenState extends State<HomeScreen> {
 | 
				
			|||||||
                      NotificationListener<ScrollNotification>(
 | 
					                      NotificationListener<ScrollNotification>(
 | 
				
			||||||
                        onNotification: (notification) {
 | 
					                        onNotification: (notification) {
 | 
				
			||||||
                          if (notification is ScrollUpdateNotification) {
 | 
					                          if (notification is ScrollUpdateNotification) {
 | 
				
			||||||
                        final offset = notification.metrics.pixels;
 | 
					                            handleScrollEvent(context);
 | 
				
			||||||
                        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<HomePageState>().showScrollMessage) {
 | 
					 | 
				
			||||||
                              context.read<HomePageState>().showScrollMessage = true;
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                          } else {
 | 
					 | 
				
			||||||
                            if (context.read<HomePageState>().showScrollMessage) {
 | 
					 | 
				
			||||||
                              context.read<HomePageState>().showScrollMessage = false;
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                          }
 | 
					 | 
				
			||||||
                        } else {
 | 
					 | 
				
			||||||
                          var offsetAmount = offset.abs();
 | 
					 | 
				
			||||||
                          if (offsetAmount > pageSwitchSensitivity) {
 | 
					 | 
				
			||||||
                            context.router.navigate(const HomeRoute());
 | 
					 | 
				
			||||||
                            setState(() {
 | 
					 | 
				
			||||||
                              _collapse = false;
 | 
					 | 
				
			||||||
                            });
 | 
					 | 
				
			||||||
                          } else {
 | 
					 | 
				
			||||||
                            if (context.read<HomePageState>().showScrollMessage) {
 | 
					 | 
				
			||||||
                              context.read<HomePageState>().showScrollMessage = false;
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                          }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                          }
 | 
					                          }
 | 
				
			||||||
                          return true;
 | 
					                          return true;
 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
                    child: ClipRect(child: HomeContent(
 | 
					                        child: Consumer<HomePageState>(
 | 
				
			||||||
                      collapse: _collapse,
 | 
					                          builder: (context, state, _) =>
 | 
				
			||||||
                    )),
 | 
					                            ClipRect(child: HomeContent(
 | 
				
			||||||
 | 
					                              controller: _controller,
 | 
				
			||||||
 | 
					                              collapse: state.collapse,
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
                      ),
 | 
					                      ),
 | 
				
			||||||
                    ],
 | 
					                    ],
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
@@ -82,6 +131,7 @@ class _HomeScreenState extends State<HomeScreen> {
 | 
				
			|||||||
              ),
 | 
					              ),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,13 +2,21 @@ import 'package:flutter/material.dart';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class HomePageState extends ChangeNotifier {
 | 
					class HomePageState extends ChangeNotifier {
 | 
				
			||||||
  bool _showScrollMessage = false;
 | 
					  bool _showScrollMessage = false;
 | 
				
			||||||
 | 
					  bool _collapse = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool get showScrollMessage {
 | 
					  bool get showScrollMessage { return _showScrollMessage; }
 | 
				
			||||||
    return _showScrollMessage;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  set showScrollMessage(bool value) {
 | 
					  set showScrollMessage(bool value) {
 | 
				
			||||||
 | 
					    if (value != _showScrollMessage) {
 | 
				
			||||||
      _showScrollMessage = value;
 | 
					      _showScrollMessage = value;
 | 
				
			||||||
      notifyListeners();
 | 
					      notifyListeners();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool get collapse { return _collapse; }
 | 
				
			||||||
 | 
					  set collapse(bool value) {
 | 
				
			||||||
 | 
					    if (value != _collapse) {
 | 
				
			||||||
 | 
					      _collapse = value;
 | 
				
			||||||
 | 
					      notifyListeners();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -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/routes/index.gr.dart';
 | 
				
			||||||
import 'package:furman_now/src/services/get_app/barcode/barcode_service.dart';
 | 
					import 'package:furman_now/src/services/get_app/barcode/barcode_service.dart';
 | 
				
			||||||
import 'package:furman_now/src/utils/theme.dart';
 | 
					import 'package:furman_now/src/utils/theme.dart';
 | 
				
			||||||
 | 
					import 'package:provider/provider.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import '../home/state.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class StudentIdScreen extends StatefulWidget {
 | 
					class StudentIdScreen extends StatefulWidget {
 | 
				
			||||||
  const StudentIdScreen({Key? key}) : super(key: key);
 | 
					  const StudentIdScreen({Key? key}) : super(key: key);
 | 
				
			||||||
@@ -44,7 +47,12 @@ class _StudentIdScreenState extends State<StudentIdScreen> {
 | 
				
			|||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return Scaffold(
 | 
					    return Scaffold(
 | 
				
			||||||
      body: Listener(
 | 
					      body: WillPopScope(
 | 
				
			||||||
 | 
					        onWillPop: () async {
 | 
				
			||||||
 | 
					          context.read<HomePageState>().collapse = false;
 | 
				
			||||||
 | 
					          return true;
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        child: Listener(
 | 
				
			||||||
          onPointerMove: (details) {
 | 
					          onPointerMove: (details) {
 | 
				
			||||||
            int sensitivity = 8;
 | 
					            int sensitivity = 8;
 | 
				
			||||||
            if (details.delta.dy > sensitivity) {
 | 
					            if (details.delta.dy > sensitivity) {
 | 
				
			||||||
@@ -128,6 +136,7 @@ class _StudentIdScreenState extends State<StudentIdScreen> {
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,7 @@ class _RestaurantsListState extends State<RestaurantsList> {
 | 
				
			|||||||
                  itemCount: restaurants.length,
 | 
					                  itemCount: restaurants.length,
 | 
				
			||||||
                  cacheExtent: 10000,
 | 
					                  cacheExtent: 10000,
 | 
				
			||||||
                  scrollDirection: Axis.horizontal,
 | 
					                  scrollDirection: Axis.horizontal,
 | 
				
			||||||
 | 
					                  physics: const BouncingScrollPhysics(),
 | 
				
			||||||
                  prototypeItem: Padding(
 | 
					                  prototypeItem: Padding(
 | 
				
			||||||
                    padding: const EdgeInsets.only(right: 15),
 | 
					                    padding: const EdgeInsets.only(right: 15),
 | 
				
			||||||
                    child: RestaurantCard(restaurant: restaurants.first),
 | 
					                    child: RestaurantCard(restaurant: restaurants.first),
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user