我想建立一个带有粘性页脚的列表视图,例如this article的“是否粘贴到底?!”在Flutter中。
在CSS中,
.main-footer{
position: sticky;
bottom: 0;
}
但是如何处理Flutter?
1和2首先显示(可滚动内容和固定页脚)。滚动到1的末尾后,页脚(2)变得不固定。其余内容(3)将显示在页脚(2)下方。
我尝试使用CustomScrollView来实现上述功能,但是页脚按钮未在列表上方绘制。
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);
}
}
}
答案 0 :(得分:1)
尝试具有三个子项的列,页眉和页脚具有特定大小,ListView 占用剩余空间。
Column(
children: [
Container(height: 100, child: HeaderWidget),
Expanded(child: ListView.builder(...)),
Container(height: 100, child: FooterWidget),
]
滚动将应用于 ListView。
答案 1 :(得分:0)
尝试此套餐
https://pub.dev/packages/sticky_infinite_list
在说明中,有一个指向示例应用程序的链接,您可以在其中使用它。
此程序包支持顶部和底部位置均为左右的粘性标头。默认情况下,它会覆盖内容,但是您可以在内容底部添加边距,以防止覆盖以及标题到达其最小偏移位置时出现
答案 2 :(得分:-1)
尝试一下
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,
),
],
),
),
);
}
}
答案 3 :(得分:-1)
如何将Stack()与ListView结合在一起,然后将列与容器放置在底部呢?它可能不是您期望的答案,但是它按预期的方式工作。我尝试过:
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,
),
],
)
],
)
答案 4 :(得分:-1)
要实现这种视图,我建议使用 Slivers。
好处:
检查下面的代码:
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),
),
),
),
),
)
],
),
);
}
}
更多细节请看这里:
https://itnext.io/create-a-header-footer-with-scrollable-body-view-in-flutter-5551087270de