[英]How to implement position: sticky and bottom 0 with Flutter?
我想建立一個帶有粘性頁腳的列表視圖,如本文的“粘到底?!” 在顫振。
在 CSS 中,
.main-footer{
position: sticky;
bottom: 0;
}
但是如何處理 Flutter?
1 和 2 在 First 中可見(可滾動內容和固定頁腳)。 滾動到 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);
}
}
}
試試 Column 有三個孩子, Header 和 Footer 有一個特定的大小, ListView 占據剩余空間。
Column(
children:[
Container(height: 100, child: HeaderWidget),
Expanded(child: ListView.builder(...)),
Container(height: 100, child: FooterWidget),
]
),
滾動將應用於 ListView。
嘗試這個
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,
),
],
),
),
);
}
}
將 Stack() 與 ListView 放在一起,然后在底部放置一個 Container 的 Column 怎么樣? 這可能不是您期望的答案,但它會按照預期的方式工作。 我試過了:
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,
),
],
)
],
)
試試這個包
https://pub.dev/packages/sticky_infinite_list
在描述中有一個示例應用程序的鏈接,您可以在其中使用它。
這個包支持頂部和底部定位的粘性標題,也可以左右兩個位置。 它默認覆蓋內容,但您可以在內容底部添加邊距,以防止覆蓋以及當標題到達其最小偏移位置時
要實現這樣的視圖,我建議使用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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.