CustomScrollView 内的 Flutter SliverPersistentHeader 在到达底部小部件之前达到 maxScrollExtend
Flutter SliverPersistentHeader inside CustomScrollView reaches maxScrollExtend before reach to the bottom widget
screenshot
我正在尝试实现可垂直滚动的堆叠式卡片列表视图。当我使用堆栈时,我无法顺利滚动它们。所以我决定使用 CustomScrollView 和 SliverPersistentHeader。不幸的是,SliverPersistentHeader 列表在滚动时无法触及底部小部件。谁能拯救我的一天?
class StackedList extends StatefulWidget {
@override
_StackedListState createState() => _StackedListState();
}
class _StackedListState extends State<StackedList> {
final List<Color> colors = Colors.primaries;
static const _minHeight = 24.0;
static const _maxHeight = 80.0;
@override
Widget build(BuildContext context) {
List<Color> _colors = List();
_colors.addAll(colors);
return CustomScrollView(
physics: ClampingScrollPhysics(),
shrinkWrap: false,
slivers: <Widget>[
..._colors
.map(
(color) => StackedListChild(
minHeight: _minHeight,
maxHeight: _maxHeight,
floating: false,
pinned: true,
child: getCard(
cardId: _colors.indexOf(color).toString(),
color: color,
),
),
)
.toList(),
],
);
}
}
class StackedListChild extends StatelessWidget {
final double minHeight;
final double maxHeight;
final bool pinned;
final bool floating;
final Widget child;
SliverPersistentHeaderDelegate get _delegate => _StackedListDelegate(
minHeight: minHeight, maxHeight: maxHeight, child: child);
const StackedListChild({
Key key,
@required this.minHeight,
@required this.maxHeight,
@required this.child,
this.pinned = false,
this.floating = false,
}) : assert(child != null),
assert(minHeight != null),
assert(maxHeight != null),
assert(pinned != null),
assert(floating != null),
super(key: key);
@override
Widget build(BuildContext context) => SliverPersistentHeader(
key: key, pinned: pinned, floating: floating, delegate: _delegate);
}
class _StackedListDelegate extends SliverPersistentHeaderDelegate {
final double minHeight;
final double maxHeight;
final Widget child;
_StackedListDelegate({
@required this.minHeight,
@required this.maxHeight,
@required this.child,
});
@override
double get minExtent => minHeight;
@override
double get maxExtent => math.max(maxHeight, minHeight);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return new SizedBox.expand(child: child);
}
@override
bool shouldRebuild(_StackedListDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
在列表末尾添加一个具有足够高度的 Sliver 视图,以便有足够的空间将 SliverPersistentHeaders 滚动到最后一个。
slivers: <Widget>[
..._colors
.map(
(color) => StackedListChild(
minHeight: _minHeight,
maxHeight: _maxHeight,
floating: false,
pinned: true,
child: getCard(
cardId: _colors.indexOf(color).toString(),
color: color,
),
),
)
.toList(),
///extra bottom padding sliver
SliverToBoxAdapter(
child: Container(
height: MediaQuery.of(context).size.height,
alignment:Alignment.center,
))
],
观看现场演示 here。
screenshot
我正在尝试实现可垂直滚动的堆叠式卡片列表视图。当我使用堆栈时,我无法顺利滚动它们。所以我决定使用 CustomScrollView 和 SliverPersistentHeader。不幸的是,SliverPersistentHeader 列表在滚动时无法触及底部小部件。谁能拯救我的一天?
class StackedList extends StatefulWidget {
@override
_StackedListState createState() => _StackedListState();
}
class _StackedListState extends State<StackedList> {
final List<Color> colors = Colors.primaries;
static const _minHeight = 24.0;
static const _maxHeight = 80.0;
@override
Widget build(BuildContext context) {
List<Color> _colors = List();
_colors.addAll(colors);
return CustomScrollView(
physics: ClampingScrollPhysics(),
shrinkWrap: false,
slivers: <Widget>[
..._colors
.map(
(color) => StackedListChild(
minHeight: _minHeight,
maxHeight: _maxHeight,
floating: false,
pinned: true,
child: getCard(
cardId: _colors.indexOf(color).toString(),
color: color,
),
),
)
.toList(),
],
);
}
}
class StackedListChild extends StatelessWidget {
final double minHeight;
final double maxHeight;
final bool pinned;
final bool floating;
final Widget child;
SliverPersistentHeaderDelegate get _delegate => _StackedListDelegate(
minHeight: minHeight, maxHeight: maxHeight, child: child);
const StackedListChild({
Key key,
@required this.minHeight,
@required this.maxHeight,
@required this.child,
this.pinned = false,
this.floating = false,
}) : assert(child != null),
assert(minHeight != null),
assert(maxHeight != null),
assert(pinned != null),
assert(floating != null),
super(key: key);
@override
Widget build(BuildContext context) => SliverPersistentHeader(
key: key, pinned: pinned, floating: floating, delegate: _delegate);
}
class _StackedListDelegate extends SliverPersistentHeaderDelegate {
final double minHeight;
final double maxHeight;
final Widget child;
_StackedListDelegate({
@required this.minHeight,
@required this.maxHeight,
@required this.child,
});
@override
double get minExtent => minHeight;
@override
double get maxExtent => math.max(maxHeight, minHeight);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return new SizedBox.expand(child: child);
}
@override
bool shouldRebuild(_StackedListDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
在列表末尾添加一个具有足够高度的 Sliver 视图,以便有足够的空间将 SliverPersistentHeaders 滚动到最后一个。
slivers: <Widget>[
..._colors
.map(
(color) => StackedListChild(
minHeight: _minHeight,
maxHeight: _maxHeight,
floating: false,
pinned: true,
child: getCard(
cardId: _colors.indexOf(color).toString(),
color: color,
),
),
)
.toList(),
///extra bottom padding sliver
SliverToBoxAdapter(
child: Container(
height: MediaQuery.of(context).size.height,
alignment:Alignment.center,
))
],
观看现场演示 here。