Flutter listview中嵌套横向滚动的SingleChildScrollView保存滚动位置

【效果图后续补上】缓存

结构是listview包含多种不一样类型的item,而后其中一个是SingleChildScrollView。
点击SingleChildScrollView中的item刷新listview中的部分数据。
可是发现当SingleChildScrollView滑动很远以后,再滑动listview,当SingleChildScrollView滑出屏幕以后,再滑回来SingleChildScrollView就回到了初始位子,这确定不行啊。
listview的item滑出屏幕以后会被回收的,设断点查看,来回滑动这个SingleChildScrollView并无从新建立,可是他里面的内容会被从新建立,这样每次从屏幕外面划回来SingleChildScrollView就回到初始状态了。markdown

接下来就是研究怎么不让它回收 重建,而后一顿查listview怎么缓存,SingleChildScrollView怎么保存滑动距离,保存状态等,查看源码发现SingleChildScrollView的controller默认是保存滑动距离的;可是由于SingleChildScrollView里面的内容都从新建立了因此滑动距离也就无用了;ide

无心中发现listview有 addAutomaticKeepAlives 这么一个属性,可是直接设置成 true又很差使,后来查了下发现它须要接收到须要保存状态的通知才会去保存item的,
查了下用法,在 StatefulWidget 的 state 中重写 wantKeepAlive,个人 SingleChildScrollView 里面的item正好都是 StatefulWidget;oop

最终参考 这个文章 修改了下 SingleChildScrollView 里面item的代码;ui

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;this

相关文章
相关标签/搜索