【发布时间】:2021-09-23 01:11:48
【问题描述】:
我正在我的颤振应用程序中开发一个视差样式的标题/背景块,它以大约 1/3 的前景内容速度向上滚动。前台的所有部分都在同一个 customScrollView 中,而后台标题位于堆栈顶部的定位容器中。
我正在使用 customscrollview 上的侦听器来更新 y 偏移整数,然后使用该整数来更新堆栈内元素的顶部位置。
虽然这可以按预期工作,但我面临的问题是滚动时会发生大量重新绘制,这在未来可能会影响性能。我确信可能有一种更有效的方法来实现这一点 - 例如将整个背景放在一个单独的子小部件中并将控制器从父小部件传递给它 - 但是我正在努力寻找有关这样做的任何信息,或者如果这是正确的方法。
有人能指出我正确的重构方向吗?
class ScrollingWidgetList extends StatefulWidget {
ScrollingWidgetList();
@override
State<StatefulWidget> createState() {
return _ScrollingWidgetList();
}
}
class _ScrollingWidgetList extends State<ScrollingWidgetList> {
ScrollController _controller;
double _offsetY = 0.0;
_scrollListener() {
setState(() {
_offsetY = _controller.offset;
});
}
@override
void initState() {
_controller = ScrollController();
_controller.addListener(_scrollListener);
super.initState();
}
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
top: -(_offsetY / 3),
child: ConstrainedBox(
constraints: new BoxConstraints(
maxHeight: 300.0,
minHeight: MediaQuery.of(context).size.width * 0.35),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
Theme.of(context).primaryColorDark,
Colors.blueGrey[900].withOpacity(0.8)
],
)),
height: MediaQuery.of(context).size.width * 0.35)),
width: MediaQuery.of(context).size.width,
),
CustomScrollView(controller: _controller, slivers: [
SliverList(
delegate: SliverChildListDelegate([
Padding(
padding: const EdgeInsets.only(top: 16.0, bottom: 8.0),
child: ListTile(
title: Padding(
padding: const EdgeInsets.only(top: 6.0),
child: Text('Header text',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: Colors.white)),
),
subtitle: Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Text('Subtitle text',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.white)),
),
))
])),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return FakeItem(
executing: false,
delay: index.isOdd,
complete: false,
cancelled: false);
},
childCount: 30,
)),
])
],
);
}
}
【问题讨论】:
-
不要在每次滚动后使用
setState- 它会重建整个小部件 - 例如使用AnimatedBuilder -
你能用条子做你的滚动效果吗?我不知道这个教程有多好,但是有一堆图像显示了不同的条子行为:raywenderlich.com/19539821-slivers-in-flutter-getting-started
-
但实际上
CustomMultiChildLayout在您的情况下比Stack/AnimatedBuilder/Positionedspaghetti 更方便 -
@pskink 是的,我开始研究 AnimatedBuilder,但我无法完全找到按照我设想的方式处理它的方法,今天我将阅读 customMultiChildLayout!
-
@pskink 嘿伙计,周末没工作。我一直在使用您的代码,并且动画构建器示例几乎是正确的。 CustomMultiChildLayout 也非常好用,但为了简单起见选择了#1。这可能是一个单独的答案,而不是线程中的评论!