flutter - Flutter 中的视差式标题滚动性能
问题描述
我正在我的颤振应用程序中开发一个视差样式的标题/背景块,它以大约 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,
)),
])
],
);
}
}
解决方案
@pskink 在评论中添加了一个很好的解决方案,但他们似乎已将其删除。对于任何寻求优雅解决方案的人来说,这是确定的基础。
您可以在下面的代码中看到有两种布局正在由CustomMultiChildLayout
. 希望这可以帮助任何寻找类似解决方案的人
class ScrollList extends StatelessWidget {
final ScrollController _controller = ScrollController();
@override
Widget build(BuildContext context) {
return CustomMultiChildLayout(
delegate: ScrollingChildComponentDelegate(_controller),
children: <Widget>[
// background element layout
LayoutId(
id: 'background',
child: DecoratedBox(
decoration: BoxDecoration(
// box decoration
),
),
),
// foreground element layout
LayoutId(
id: 'scrollview',
child: CustomScrollView(
controller: _controller,
physics: AlwaysScrollableScrollPhysics(),
slivers: [
SliverToBoxAdapter(
child: ListTile(
title: Text('TitleText'),
),
subtitle: Text('SubtitleText'),
)),
),
SliverList(
delegate: SliverChildBuilderDelegate(itemBuilder,
childCount: 100),
),
],
)),
],
);
}
}
// itembuilder for child components
Widget itemBuilder(BuildContext context, int index) {
return Card(
margin: EdgeInsets.all(6),
child: ClipPath(
clipper: ShapeBorderClipper(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10))),
child: Container(
// child element content
)));
}
// controller for the animation
class ScrollingChildComponentDelegate extends MultiChildLayoutDelegate {
final ScrollController _controller;
ScrollingChildComponentDelegate(this._controller) : super(relayout: _controller);
@override
void performLayout(Size size) {
positionChild('background', Offset(0, -_controller.offset / 3));
layoutChild('background',
BoxConstraints.tightFor(width: size.width, height: size.height * 0.2));
positionChild('scrollview', Offset.zero);
layoutChild('scrollview', BoxConstraints.tight(size));
}
@override
bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) => true;
}
推荐阅读
- c# - 带有 Stringbuilder 的 C#“编码器”
- sql - SQL:选择用户ID,如果一个条目具有特定值,则排除所有用户ID
- azure - 可从 azure Web 应用程序多容器访问的 Docker.sock
- java - 使用 java config 缺少 bean 工厂的 TCP 客户端
- mysql - How to configure a one to many relationship in Sequelize?
- reactjs - 反应超时竞争条件
- hyperledger - 为什么我无法部署超级账本作曲家项目
- oracle - 在 PLSQL 中创建触发器--接收错误消息
- flutter - 如何在颤动中呈现一个空视图?
- java - 如何修复在java中读取文件