I need to implement filters at the top of the screen. The idea is that when you scroll down, the filters should disappear, but the title and leading widget should remain visible. Additionally, when scrolling up, the filters should reappear. Does anyone have any suggestions on how to achieve this, what is the best use for this for this feature?
you achive this using ScrollController to detect scroll direction and a combination of SliverAppBar and SliverPersistentHeader for the layout.
import 'package:flutter/material.dart';
class ScrollableFiltersPage extends StatefulWidget {
@override
_ScrollableFiltersPageState createState() => _ScrollableFiltersPageState();
}
class _ScrollableFiltersPageState extends State<ScrollableFiltersPage> {
final ScrollController _scrollController = ScrollController();
bool _showFilters = true;
double _lastOffset = 0;
@override
void initState() {
super.initState();
_scrollController.addListener(() {
if (_scrollController.offset > _lastOffset && _showFilters) {
setState(() => _showFilters = false); // Scrolling down
} else if (_scrollController.offset < _lastOffset && !_showFilters) {
setState(() => _showFilters = true); // Scrolling up
}
_lastOffset = _scrollController.offset;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
controller: _scrollController,
slivers: [
SliverAppBar(
pinned: true,
title: Text('Title'),
leading: Icon(Icons.menu),
),
SliverPersistentHeader(
pinned: true,
delegate: _FiltersDelegate(
showFilters: _showFilters,
child: Container(
color: Colors.blueGrey,
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
TextButton(onPressed: () {}, child: Text("Filter 1")),
TextButton(onPressed: () {}, child: Text("Filter 2")),
TextButton(onPressed: () {}, child: Text("Filter 3")),
],
),
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(title: Text('Item $index')),
childCount: 50,
),
),
],
),
);
}
}
class _FiltersDelegate extends SliverPersistentHeaderDelegate {
final bool showFilters;
final Widget child;
_FiltersDelegate({required this.showFilters, required this.child});
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return AnimatedOpacity(
duration: Duration(milliseconds: 200),
opacity: showFilters ? 1.0 : 0.0,
child: child,
);
}
@override
double get maxExtent => 50.0;
@override
double get minExtent => 50.0;
@override
bool shouldRebuild(covariant _FiltersDelegate oldDelegate) =>
showFilters != oldDelegate.showFilters || child != oldDelegate.child;
}
I HOPE THIS IS HELP YOU. THANK YOU:)