Repository: flutter
Issue: NestedScrollView's use of PrimaryScrollController/AutomaticKeepAliveClientMixin/PageStorageKey breaks when there are multiple inner ScrollPositions
Labels: framework,f: scrolling,has reproducible steps,P2,workaround available,team-framework,triaged-framework,found in release: 3.24

### Steps to reproduce

https://github.com/flutter/flutter/pull/157756/files this pr, it's not fixed those issues.

* https://github.com/flutter/flutter/issues/62833
* https://github.com/flutter/flutter/issues/81619
* https://github.com/flutter/flutter/issues/21868
* https://github.com/flutter/flutter/issues/36419

The reason is that  the scroll list in NestedScrollView's body are cached, they are not removed from ScrollController, so when tap on other tab, and scroll the list, it will change all of postions in ScrollController.





### Expected results

on scroll current tab list

### Actual results

all of tab list are scroll

### Code sample

<details open><summary>Code sample</summary>

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(home: MyApp()));
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<StatefulWidget> createState() {
    return MyAppState();
  }
}

class MyAppState extends State<MyApp> with TickerProviderStateMixin {
  final List<ListItem> listData = [];
  ScrollController sc = ScrollController(initialScrollOffset: 0.0);
  late TabController tc;

  @override
  void initState() {
    tc = TabController(length: 2, vsync: this);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: Text('Test')), body: getBody());
  }

  Widget getBody() {
    return NestedScrollView(
      controller: sc,

      body: Column(
        children: [
          TabBar(tabs: [Tab(text: 'tab1'), Tab(text: 'tab2')], controller: tc),
          Expanded(
            child: TabBarView(
              controller: tc,
              children: <Widget>[
                ListBuilder(name: Icons.abc, count: 40),
                ListBuilder(name: Icons.accessibility, count: 50),
              ],
            ),
          ),
        ],
      ),
      headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
        return [];
      },
    );
  }
}

class ListItem {
  final String title;
  final IconData iconData;

  ListItem(this.title, this.iconData);
}

class ListBuilder extends StatefulWidget {
  final int count;
  final IconData name;
  const ListBuilder({required this.count, required this.name, super.key});
  @override
  _LoadImgByLocAppPageState createState() =>
      _LoadImgByLocAppPageState(count, name);
}

class _LoadImgByLocAppPageState extends State
    with AutomaticKeepAliveClientMixin {
  IconData name;
  _LoadImgByLocAppPageState(this.count, this.name);
  int count = 20;
  final List<ListItem> listData = [];
  @override
  void initState() {
    for (int i = 0; i < count; i++) {
      listData.add(ListItem("Item$i", name));
    }

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);

    return SafeArea(
      top: false,
      bottom: false,
      child: Builder(
        // This Builder is needed to provide a BuildContext that is "inside"
        // the NestedScrollView, so that sliverOverlapAbsorberHandleFor() can
        // find the NestedScrollView.
        builder: (BuildContext context) {
          return CustomScrollView(
            slivers: <Widget>[
              SliverPadding(
       
                padding: const EdgeInsets.all(8.0),
                // In this example, the inner scroll view has
                // fixed-height list items, hence the use of
                // SliverFixedExtentList. However, one could use any
                // sliver widget here, e.g. SliverList or SliverGrid.
                sliver: SliverFixedExtentList(
                  // The items in this example are fixed to 48 pixels
                  // high. This matches the Material Design spec for
                  // ListTile widgets.
                  itemExtent: 48.0,
                  delegate: SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                      // This builder is called for each child.
                      // In this example, we just number each list item.
                      return Text(index.toString());
                    },
                    // The childCount of the SliverChildBuilderDelegate
                    // specifies how many children this inner list
                    // has. In this example, each tab has a list of
                    // exactly 30 items, but this is arbitrary.
                    childCount: listData.length,
                  ),
                ),
              ),
            ],
          );
        },
      ),
    );
  }

  @override
  bool get wantKeepAlive => true;
}

```

</details>


### Screenshots or Video

<details open>
<summary>Screenshots / Video demonstration</summary>

[Upload media here]

</details>


### Logs

<details open><summary>Logs</summary>

```console
[Paste your logs here]
```

</details>


### Flutter Doctor output

<details open><summary>Doctor output</summary>

```console
[✓] Flutter (Channel master, 3.27.0-1.0.pre.552, on macOS 15.1 24B83 darwin-arm64, locale
    zh-Hans-CN)
    • Flutter version 3.27.0-1.0.pre.552 on channel master
```

</details>