问题
I want to build a list view with sticky footer like this article's "Stick to the bottom?!" in Flutter.
In CSS,
.main-footer{
position: sticky;
bottom: 0;
}
but how to do with Flutter?
What I want
- Scrollable large content
- Footer (sticky)
- Scrollable large content
1 and 2 are visible at First (Scrollable content and fixed footer). After scroll to end of 1, Footer (2) become not fixed. Rest of contents (3) will be shown below footer(2).
I tried to implement above with CustomScrollView but footer button is not drawn above list.
code
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fixed footer',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: _FixedFooterDemo(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
),
),
);
}
}
class _FixedFooterDemo extends StatelessWidget {
const _FixedFooterDemo({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: <Widget>[
SliverAppBar(
title: Text('Fixed footer'),
),
SliverList(
delegate: SliverChildListDelegate(List.generate(20, _buildListItem)),
),
SliverStickyFooter(
child: Center(
child: RaisedButton(
onPressed: () {},
child: Text('Fixed under list button'),
),
),
),
SliverFillRemaining(
child: Container(
color: Colors.yellow,
child: Center(
child: Text('below space'),
),
),
),
],
);
}
ListTile _buildListItem(int i) {
return ListTile(
title: Text(
'Item $i',
),
subtitle: Text(
'Sit est ipsum consequat sit ex. Minim magna laborum dolore aliqua sit dolore velit sint fugiat. Culpa officia tempor proident minim aliquip nisi reprehenderit ullamco duis mollit. Aute velit irure ut Lorem pariatur anim mollit cillum dolor irure quis. Eu officia dolore deserunt do est cupidatat duis elit. Pariatur magna reprehenderit aliquip ea irure Lorem sunt aute.',
maxLines: 2,
),
);
}
}
class SliverStickyFooter extends SingleChildRenderObjectWidget {
const SliverStickyFooter({
Key key,
Widget child,
}) : super(key: key, child: child);
@override
RenderSliverStickyFooter createRenderObject(BuildContext context) =>
RenderSliverStickyFooter();
}
class RenderSliverStickyFooter extends RenderSliverSingleBoxAdapter {
/// Creates a [RenderSliver] that wraps a [RenderBox] which is sized to fit
/// the remaining space in the viewport.
RenderSliverStickyFooter({
RenderBox child,
}) : super(child: child);
@override
void performLayout() {
child?.layout(
constraints.asBoxConstraints(),
parentUsesSize: true,
);
final paintedChildSize =
calculatePaintOffset(constraints, from: 0.0, to: child.size.height);
assert(paintedChildSize.isFinite);
assert(paintedChildSize >= 0.0);
geometry = SliverGeometry(
scrollExtent: child.size.height,
paintExtent: paintedChildSize,
maxPaintExtent: paintedChildSize,
hasVisualOverflow: true,
paintOrigin: -child.size.height + paintedChildSize,
visible: true,
);
if (child != null) {
setChildParentData(child, constraints, geometry);
}
}
}
回答1:
Try this
import 'package:flutter/material.dart';
class Sticky extends StatefulWidget {
Sticky({Key key}) : super(key: key);
_StickyState createState() => _StickyState();
}
class _StickyState extends State<Sticky> {
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Stack(
children: <Widget>[
Positioned(
child: Container(
color: Colors.black38,
height: 60,
width: MediaQuery.of(context).size.width,
child: Text('Header'),
),
top: 0,
),
Positioned(
child: Container(
child: Text('Content'),
),
top: 60,
),
Positioned(
child: Container(
color: Colors.black38,
height: 60,
width: MediaQuery.of(context).size.width,
child: Text('Footer'),
),
bottom: 0,
),
],
),
),
);
}
}
回答2:
What about having a Stack() with a ListView and then placing a Column with a Container placed at the bottom? It might isn't the answer you expect, but it works the way it's expected to. I tried thit:
Stack(
children: <Widget>[
ListView.builder(
itemCount: 30,
itemBuilder: (context, index) {
return Container(
child: Text(
"Text\n"),
);
},
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
width: double.infinity,
height: 60,
child: Text("That's the footer"),
color: Colors.blue,
),
],
)
],
)
回答3:
Try this package
https://pub.dev/packages/sticky_infinite_list
In description there is a link to example app where you can play around with it.
This package supports sticky headers with top and bottom positioning also as left and right for both. It overlays content by default, but you can add margin to the bottom of your content, to prevent overlay and when header reaches it's min offset position
回答4:
Try Column with three children, Header and Footer have a specific size and ListView Occupies the remaining of the space.
Column(
children: [
Container(height: 100, child: HeaderWidget),
Expanded(child: ListView.builder(...)),
Container(height: 100, child: FooterWidget),
]
Scroll will be applied on the ListView.
回答5:
To implement such view i recommend using Slivers.
benefits:
- Sticky header/Footer.
- infinity body/content scroll.
check the code below:
import 'package:flutter/material.dart';
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildListDelegate(
[
Container(
width: double.infinity,
height: 50,
color: Colors.orangeAccent,
child: Center(
child: Text(
'Header',
style: TextStyle(color: Colors.white, letterSpacing:4),
),
),
),
ListView.builder(
shrinkWrap: true,
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Center(child: Text('$index')),
);
},
),
],
),
),
SliverFillRemaining(
hasScrollBody: false,
child: Align(
alignment: Alignment.bottomCenter,
child: Container(
width: double.infinity,
height: 50,
color: Colors.blueAccent,
child: Center(
child: Text(
'Footer',
style: TextStyle(color: Colors.white, letterSpacing: 4),
),
),
),
),
)
],
),
);
}
}
For more detail take a look here:
https://itnext.io/create-a-header-footer-with-scrollable-body-view-in-flutter-5551087270de
来源:https://stackoverflow.com/questions/55862884/how-to-implement-position-sticky-and-bottom-0-with-flutter