import 'package:fladder/util/adaptive_layout.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class HideOnScroll extends ConsumerStatefulWidget { final Widget? child; final ScrollController? controller; final double height; final Widget? Function(bool visible)? visibleBuilder; final Duration duration; const HideOnScroll({ this.child, this.controller, this.height = kBottomNavigationBarHeight, this.visibleBuilder, this.duration = const Duration(milliseconds: 200), super.key, }) : assert(child != null || visibleBuilder != null); @override ConsumerState createState() => _HideOnScrollState(); } class _HideOnScrollState extends ConsumerState { late final scrollController = widget.controller ?? ScrollController(); bool isVisible = true; bool atEdge = false; @override void initState() { super.initState(); scrollController.addListener(listen); } @override void dispose() { scrollController.removeListener(listen); super.dispose(); } void listen() { final direction = scrollController.position.userScrollDirection; if (scrollController.offset < scrollController.position.maxScrollExtent) { if (direction == ScrollDirection.forward) { if (!isVisible) { setState(() => isVisible = true); } } else if (direction == ScrollDirection.reverse) { if (isVisible) { setState(() => isVisible = false); } } } else { setState(() { isVisible = true; }); } } @override Widget build(BuildContext context) { if (widget.visibleBuilder != null) return widget.visibleBuilder!(isVisible)!; if (widget.child == null) return const SizedBox(); if (AdaptiveLayout.of(context).layout == LayoutState.desktop) { return widget.child!; } else { return AnimatedAlign( alignment: const Alignment(0, -1), heightFactor: isVisible ? 1.0 : 0, duration: widget.duration, child: Wrap(children: [widget.child!]), ); } } }