From 838b2168d7fe8792f2c661d7f8ac27f9ec9cba14 Mon Sep 17 00:00:00 2001 From: EsinShadrach Date: Wed, 31 Jul 2024 06:06:19 +0100 Subject: [PATCH] Added Sticky Header --- lib/main.dart | 1 + lib/routes.dart | 3 + .../sticky_header/sticky_header_screen.dart | 99 +++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 lib/screens/sticky_header/sticky_header_screen.dart diff --git a/lib/main.dart b/lib/main.dart index 26417bf..1ac8c69 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -109,6 +109,7 @@ class HomePage extends StatelessWidget { body: SafeArea( child: ListView( children: [ + Text(routes().keys.toString()), CupertinoListSection.insetGrouped( backgroundColor: context.colorScheme.inverseSurface.withOpacity(0.02), diff --git a/lib/routes.dart b/lib/routes.dart index ddb18d6..9ba801b 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -6,6 +6,7 @@ import "package:flutter_playground/screens/examples/overlay_example/overlay_exam import "package:flutter_playground/screens/examples/scale_down_btn/scale_down_btn_example.dart"; import "package:flutter_playground/screens/page_animation/page_animation.dart"; import "package:flutter_playground/screens/stacks/stacked_cards.dart"; +import "package:flutter_playground/screens/sticky_header/sticky_header_screen.dart"; import "package:flutter_playground/screens/top_snackbar/top_snackbar.dart"; mixin AppRoutes { @@ -17,6 +18,7 @@ mixin AppRoutes { static const String heroWidget = "/hero-widget"; static const String topSnackbar = "/top-snackbar"; static const String stack = "/stack"; + static const String stickerHeader = "/sticky-header"; } Map routes() => { @@ -28,4 +30,5 @@ Map routes() => { AppRoutes.heroWidget: (context) => const HeroWidgetScreen(), AppRoutes.topSnackbar: (context) => const TopSnackbar(), AppRoutes.stack: (context) => const StackedCards(), + AppRoutes.stickerHeader: (context) => const StickyHeaderScreen(), }; diff --git a/lib/screens/sticky_header/sticky_header_screen.dart b/lib/screens/sticky_header/sticky_header_screen.dart new file mode 100644 index 0000000..f32bf60 --- /dev/null +++ b/lib/screens/sticky_header/sticky_header_screen.dart @@ -0,0 +1,99 @@ +import "package:flutter/material.dart"; + +class StickyHeaderScreen extends StatelessWidget { + const StickyHeaderScreen({super.key}); + + @override + Widget build(BuildContext context) { + return const StickyHeaderExample(); + } +} + +class StickyHeaderExample extends StatelessWidget { + const StickyHeaderExample({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: CustomScrollView( + slivers: [ + SliverList( + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return ListTile( + title: Text("Item $index"), + ); + }, + childCount: 50, // Adjust this to change the number of list items + ), + ), + SliverPersistentHeader( + pinned: true, + floating: true, + delegate: _StickyHeaderDelegate( + minHeight: 60.0, + maxHeight: 60.0, + child: Container( + color: Colors.red, + padding: const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 30, + ), + child: const SafeArea( + child: Center( + child: Text( + "Pinned Header", + style: TextStyle(color: Colors.white), + ), + ), + ), + ), + ), + ), + // This is the scrollable content + SliverList( + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return ListTile( + title: Text("Item $index"), + ); + }, + childCount: 50, // Adjust this to change the number of list items + ), + ), + ], + ), + ); + } +} + +class _StickyHeaderDelegate extends SliverPersistentHeaderDelegate { + final double minHeight; + final double maxHeight; + final Widget child; + + _StickyHeaderDelegate({ + required this.minHeight, + required this.maxHeight, + required this.child, + }); + + @override + double get minExtent => minHeight; + + @override + double get maxExtent => maxHeight; + + @override + Widget build( + BuildContext context, double shrinkOffset, bool overlapsContent) { + return SizedBox.expand(child: child); + } + + @override + bool shouldRebuild(_StickyHeaderDelegate oldDelegate) { + return maxHeight != oldDelegate.maxHeight || + minHeight != oldDelegate.minHeight || + child != oldDelegate.child; + } +}