You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scaffold嵌套NestedScrollView时点击SliverAppbar下内容自动滚顶问题

问题根因

代码中手动将NestedScrollView的主滚动控制器绑定给了内部的ListView,破坏了NestedScrollView原生的嵌套滚动协调逻辑:点击列表项时触发了滚动位置矫正规则,就会出现自动滚动到顶部的异常。同时如果要在Tab内部使用带悬浮按钮的Scaffold,需要额外配置避免Scaffold占用主滚动控制器。

修复方案
  • 删掉内部ListView的controller: scrollController配置,NestedScrollView默认会自动处理内外层滚动的协调逻辑,不需要手动绑定控制器
  • 给Tab页内部的Scaffold添加primary: false配置,避免Scaffold默认抢占主滚动控制器导致嵌套滚动异常
修复后可运行代码
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: MyStatelessWidget(),
    );
  }
}

class MyStatelessWidget extends StatelessWidget {
  MyStatelessWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: NestedScrollView(
        headerSliverBuilder: (context, innerBoxIsScrolled) {
          return [
            SliverAppBar(
              floating: true,
              pinned: true,
              bottom: const TabBar(
                tabs: [
                  Tab(text: "Tab1"),
                  Tab(text: "Tab2"),
                  Tab(text: "Tab3"),
                ],
              ),
              title: const Text(
                'Appbar',
                style: TextStyle(color: Colors.black),
              ),
              expandedHeight: 180,
            ),
          ];
        },
        body: TabBarView(
          children: [
            // 每个Tab页都是独立的带悬浮按钮的Scaffold
            _buildTabPage(0),
            _buildTabPage(1),
            _buildTabPage(2),
          ],
        ),
      ),
    );
  }

  Widget _buildTabPage(int tabIndex) {
    return Scaffold(
      // 关键配置:禁止当前Scaffold抢占主滚动控制器
      primary: false,
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: const Icon(Icons.add),
      ),
      body: ListView.separated(
        padding: EdgeInsets.zero,
        itemBuilder: (context, index) {
          return Container(
            height: 100,
            width: double.infinity,
            alignment: Alignment.centerLeft,
            child: Text('Tab $tabIndex Index: $index'),
          );
        },
        itemCount: 1000,
        separatorBuilder: (BuildContext context, int index) {
          return const Divider();
        },
      ),
    );
  }
}
补充说明

如果需要主动控制内部列表的滚动位置,可以给每个子页的ListView单独创建独立的ScrollController,不要复用NestedScrollView的主控制器即可。


内容的提问来源于stack exchange,提问作者Khoa Le

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 05:27:02