I've been trying for a while now but I cannot get it to work.
I want to create a list view in a CustomScrollView
with a CupertinoSliverNavigationBar
. The SliverList
has to be scrollable horizontally. Also, it should have one header row that sticks to the top of the view.
Please see the example here: https://dartpad.dev/?id=38c0825f27c1b3395dd22794a2567e64. Note that the body can be scrolled horizontally.
I want to make the red header row sticky so that it remains visible at all times while the blue content is scrolling.
Problem is that the header row must be inside the SingleChildScrollView
and the SizedBox
because otherwise it would not have the required width. But once it is inside there I cannot make it sticky anymore.
Many thanks for any pointers.
Solution ^^ use SliverPersistentHeader to make the red header row sticky and use SliverList instead of ListView.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'dart:math' as math;
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final scrollController = ScrollController();
return MaterialApp(
home: Scaffold(
body: CustomScrollView(
slivers: [
const CupertinoSliverNavigationBar(
largeTitle: Text('Search'),
),
//CupertinoSliverRefreshControl(),
SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 20.0,
maxHeight: 30.0,
child: Container(
color: Colors.red, child: Center(child:
Text("red header "))),
),
),
SliverList(
delegate: SliverChildListDelegate(
List.generate(80, (index) => Container(
padding: const EdgeInsets.all(5),
color: Colors.blueAccent.shade100,
child: const Text('bar'),
)),
),
),
],
),
),
);
}
}
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate({
required this.minHeight,
required this.maxHeight,
required this.child,
});
final double minHeight;
final double maxHeight;
final Widget child;
@override
double get minExtent => minHeight;
@override
double get maxExtent => math.max(maxHeight, minHeight);
@override
Widget build(BuildContext context,
double shrinkOffset,
bool overlapsContent) {
return new SizedBox.expand(child: child);
}
@override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With