Reputation: 6505
I'm trying to create a scrolling list that can have a footer at the bottom of the scrolling list. If the list does not fill up all of the vertical screen space, the footer will need to shift down to the bottom of the page.
I tried implementing this with a SliverList
and SliverFillRemaining
in a CustomScrollView
but the SliverFillRemaining
shows some unexpected behavior I believe. It fills up more space than needed (see gif).
I used the following piece of code to create this list:
child: new CustomScrollView(
slivers: <Widget>[
new SliverList(
delegate: new SliverChildBuilderDelegate(
(BuildContext context, int index) {
return new Card(
child: new Container(
padding: new EdgeInsets.all(20.0),
child: new Center(child: new Text("Card $index")),
),
);
},
childCount: 3,
),
),
new SliverPadding(
padding: new EdgeInsets.all(5.0),
),
new SliverFillRemaining(
child: new Container(
color: Colors.red,
),
)
],
)
Upvotes: 35
Views: 41106
Reputation: 101
This Package does exactly what you are expecting, I've been trying for days now,and finally used this, Its works the same way as the SliverToBoxAdapter but extends enough and does not cause over scroll
child: CustomScrollView(
slivers: <Widget>[
new SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Card(
child: Container(
padding: EdgeInsets.all(20.0),
child: Center(child: new Text("Card $index")),
),
);
},
childCount: 3,
),
),
SliverPadding(
padding: EdgeInsets.all(5.0),
),
SliverFillRemainingBoxAdapter(
child: Container(
color: Colors.red,
),
)
],
)
Upvotes: 1
Reputation: 76
Scaffold(
appBar: AppBar(title: Text('SliverFillRemaining')),
body: CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
FlutterLogo(size: 200),
Text(
'This is some longest text that should be centered'
'together with the logo',
textAlign: TextAlign.center,
),
],
),
),
],
),
);
Upvotes: 3
Reputation: 647
For anyone that is looking for an answer to this, I have a solution that has been working well whenever I needed something similar.
This is how I've managed it:
class ScrollOrFitBottom extends StatelessWidget {
final Widget scrollableContent;
final Widget bottomContent;
ScrollOrFitBottom({this.scrollableContent, this.bottomContent});
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: <Widget>[
SliverFillRemaining(
hasScrollBody: false,
child: Column(
children: <Widget>[
Expanded(child: scrollableContent),
bottomContent
],
),
),
],
);
}
}
As the name says, it will scroll if there is too much content, or have something pushed to the bottom otherwise.
I think it is simple and self-explanatory, but let me know if you have any questions
Example: https://codepen.io/lazarohcm/pen/xxdWJxb
Upvotes: 35
Reputation: 149
See my answer here and a Gist file here. It may lead you in the right direction.
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: constraints.copyWith(
minHeight: constraints.maxHeight,
maxHeight: double.infinity,
),
child: IntrinsicHeight(
child: Column(
children: <Widget>[
Container(height: 200, color: Colors.blue),
Container(height: 200, color: Colors.orange),
Container(height: 200, color: Colors.green),
Container(height: 50, color: Colors.pink),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Container(
width: double.infinity,
color: Colors.red,
padding: EdgeInsets.all(12.0),
child: Text('FOOTER', textAlign: TextAlign.center,),
),
),
),
],
),
),
),
);
}
);
}
Upvotes: -4
Reputation: 5351
SliverFillRemaining
will automatically size itself to fill the space between the bottom of the last list item and the bottom of the viewport. See the performLayout
method of SliverFillRemaining
for the code:
I don't think you can use it to achieve the effect you're going for, though you might be able to create a subclass that would work.
Upvotes: 7