问题
For the last few days, I've been reading through flutter framework documentation and especially the sliver part but I'm not quite sure where to start. I'm trying to implement the sticky headers and snap effect. Might the RenderSliverList be a good start? Do I need to re-layout things? Do I need to do additional drawing? And if so where?
Any help on where to start would be a huge help, thanks in advance!
Edit: I think I understood the layout part now, but I just can't find where the painting is supposed to happen.
Edit 2: For clarification, this is the desired "sticky header effect":
How can I make sticky headers in RecyclerView? (Without external lib)
and this is the "snap" effect:
https://rubensousa.github.io/2016/08/recyclerviewsnap
回答1:
For the "sticky header effect" I ran into this problem myself, so I created this package to manage sticky headers with slivers: https://github.com/letsar/flutter_sticky_header
To use it you have to create one SliverStickyHeader per section in a CustomScrollView.
One section can be wrote like this:
new SliverStickyHeader(
header: new Container(
height: 60.0,
color: Colors.lightBlue,
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: new Text(
'Header #0',
style: const TextStyle(color: Colors.white),
),
),
sliver: new SliverList(
delegate: new SliverChildBuilderDelegate(
(context, i) => new ListTile(
leading: new CircleAvatar(
child: new Text('0'),
),
title: new Text('List tile #$i'),
),
childCount: 4,
),
),
);
If you want, the entire source code for the above demo is here: https://github.com/letsar/flutter_sticky_header/blob/master/example/lib/main.dart
I hope this will help you.
回答2:
It's dead simple :
Use a CustomScrollView and give it as child both a SliverList and a SliverAppBar. You may replace the SliverList with a SliverGrid if you need to.
Then, depending on the effect you want to achieve, there are a few properties you may set on SliverAppBar:
- snap
- expandedHeight (+ flexibleSpace)
- floating
- pinned
In the end, you may have something similar to :
new CustomScrollView(
slivers: <Widget>[
new SliverAppBar(
title: new Text("Title"),
snap: true,
floating: true,
),
new SliverFixedExtentList(
itemExtent: 50.0,
delegate: new SliverChildBuilderDelegate(
(BuildContext context, int index) {
return new Container(
alignment: Alignment.center,
color: Colors.lightBlue[100 * (index % 9)],
child: new Text('list item $index'),
);
},
),
),
],
)
Even better, you can concatenate different scroll behaviour inside a single CustomScrollView. Which means you can potentially have a grid followed by a list just by adding a SliverGrid as a child to your scrollView.
I know I know, flutter is awesome.
回答3:
I managed to do the stickyheader effect on Flutter for an iOS app using the following code - credit goes to this piece of code written here from where I drew my inspiration (https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/animation/home.dart#L112):
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate({
@required this.collapsedHeight,
@required this.expandedHeight,}
);
final double expandedHeight;
final double collapsedHeight;
@override double get minExtent => collapsedHeight;
@override double get maxExtent => math.max(expandedHeight, minExtent);
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return new Container(color: Colors.red,
child: new Padding(
padding: const EdgeInsets.only(
left: 8.0, top: 8.0, bottom: 8.0, right: 8.0),
child: new Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new Text("Time"), new Text("Price"), new Text("Hotness")
],
),
)
);
}
@override
bool shouldRebuild(@checked _SliverAppBarDelegate oldDelegate) {
return expandedHeight != oldDelegate.expandedHeight
|| collapsedHeight != oldDelegate.collapsedHeight;
}
}
To make it sticky, add the _SliverAppBarDelegate to the silvers widget list:
new SliverPersistentHeader(delegate: new _SliverAppBarDelegate(collapsedHeight: 36.0, expandedHeight: 36.0), pinned: true, ),
I'm not really sure how to make the _SliverAppBarDelegate wrap the content though, I had to provide it with a size of 36 logical pixels to get it to work. If anyone know how it could just wrap content, please drop a comment to the answer below.
来源:https://stackoverflow.com/questions/48606995/flutter-implement-sticky-headers-and-the-snap-to-item-effect