【效果图后续补上】
结构是listview包含多种不同类型的item,然后其中一个是SingleChildScrollView。
点击SingleChildScrollView中的item刷新listview中的部分数据。
但是发现当SingleChildScrollView滑动很远之后,再滑动listview,当SingleChildScrollView滑出屏幕之后,再滑回来SingleChildScrollView就回到了初始位子,这肯定不行啊。
listview的item滑出屏幕之后会被回收的,设断点查看,来回滑动这个SingleChildScrollView并没有重新创建,但是他里面的内容会被重新创建,这样每次从屏幕外面划回来SingleChildScrollView就回到初始状态了。
接下来就是研究怎么不让它回收 重建,然后一顿查listview怎么缓存,SingleChildScrollView怎么保存滑动距离,保存状态等,查看源码发现SingleChildScrollView的controller默认是保存滑动距离的;但是因为SingleChildScrollView里面的内容都重新创建了所以滑动距离也就无用了;
无意中发现listview有 addAutomaticKeepAlives 这么一个属性,但是直接设置成 true又不好使,后来查了下发现它需要接收到需要保存状态的通知才会去保存item的,
查了下用法,在 StatefulWidget 的 state 中重写 wantKeepAlive,我的 SingleChildScrollView 里面的item正好都是 StatefulWidget;
最终参考 这个文章 修改了下 SingleChildScrollView 里面item的代码;
class TextWidget extends StatefulWidget {
final Key key;
final String text;
final bool selected;
// 接收一个Key
TextWidget(this.key, this.text, this.selected);
@override
State<StatefulWidget> createState() => TextWidgetState(this.text, this.selected);
}
class TextWidgetState extends State<TextWidget> with AutomaticKeepAliveClientMixin {
String _text = "0";
bool _selected = false;
TextWidgetState(this._text, this._selected);
@override
Widget build(BuildContext context) {
super.build(context);
return Text(
_text,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: _selected ? 18 : 16,
fontWeight: _selected ? FontWeight.bold : FontWeight.normal,
color: _selected ? color333 : color777),
);
}
void onPressed(bool selected) {
setState(() => _selected = selected);
}
@override
bool get wantKeepAlive => true;
}
重要的是 with AutomaticKeepAliveClientMixin 和@override bool get wantKeepAlive => true;