我想建立一个带有粘性页脚的列表视图,例如本文的“粘到底?!”在颤振中。
In CSS,
.main-footer{
position: sticky;
bottom: 0;
}
但是 Flutter 该怎么办呢?
我想要的是
- 可滚动的大内容
- 页脚(粘性)
- 可滚动的大内容
1 和 2 在 First 处可见(可滚动内容和固定页脚)。滚动到 1 末尾后,页脚 (2) 变得不固定。其余内容 (3) 将显示在页脚 (2) 下方。
我尝试用上面的方法来实现自定义滚动视图但页脚按钮未绘制在列表上方。
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);
}
}
}