Search code examples
flutterdartlistviewflutter-layout

Horizontal SingleChildScrollView position changes inside a ListView when scrolling


I have a ListView with some items in it, including a SingleChildScrollView:

ListView(
  children: [
    SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      physics: const ClampingScrollPhysics(),
      primary: false,
      child: Padding(
        padding: const EdgeInsets.only(bottom: 10),
        child: Row(
          children: [
            // Container(height: 50, width: 200)
          ],
        ),
      ),
    ),
    Container(height: 1000),
  ],
)

When I scroll all the way down and all the way up, the SingleChildScrollView has scrolled items all the way to the end on its own. I understand that ListView caches what it shows, but is it possible to preserve the scroll position of the SingleChildScrollView to whatever the user had scrolled it to?


Solution

  • I am aware of two methods, once is increasing cacheExtent with addAutomaticKeepAlives value on ListView, another is using AutomaticKeepAliveClientMixin.

    ListView(
      cacheExtent: 2122,// depend on your case
      addAutomaticKeepAlives: true,
      children: [
        SingleChildScrollView(
          restorationId: "Scroll Item",
          scrollDirection: Axis.horizontal,
          physics: const ClampingScrollPhysics(),
    

    Second way is using AutomaticKeepAliveClientMixin,

    class MyHorizontalListView extends StatefulWidget {
      const MyHorizontalListView({super.key});
    
      @override
      State<MyHorizontalListView> createState() => _MyHorizontalListViewState();
    }
    
    class _MyHorizontalListViewState extends State<MyHorizontalListView>
        with AutomaticKeepAliveClientMixin {
      @override
      bool get wantKeepAlive => true;
      
      @override
      Widget build(BuildContext context) {
        super.build(context);
        return SingleChildScrollView(
    

    And place it on ListView. There might be some short way, idk,