NestedScrollView 与 SliverAppBar 导致意外的正文填充

Flo*_*uer 4 dart nestedscrollview flutter flutter-sliver flutter-sliverappbar

当我运行此代码时,ListView 将具有意外的顶部填充。(见截图)为什么会这样?有办法避免这种情况吗?

\n

我已经尝试过 SliverOverlapAbsorber、SafeArea 和 MediaQuery 来修复填充,但到目前为止似乎没有任何效果。

\n
import \'package:flutter/material.dart\';\n\nvoid main() {\n  runApp(MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      home: MyHomePage(),\n    );\n  }\n}\n\nclass MyHomePage extends StatelessWidget {\n  MyHomePage({Key? key}) : super(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      body: NestedScrollView(\n        headerSliverBuilder: (context, innerBoxIsScrolled) => [\n          SliverAppBar(\n            pinned: true,\n            title: Text(\'Title\'),\n          ),\n        ],\n        body: ListView.builder(\n          itemCount: 24,\n          itemBuilder: (context, index) => Container(\n            height: 40,\n            alignment: Alignment.center,\n            color: Colors.yellow,\n            margin: EdgeInsets.only(top: index != 0 ? 8 : 0),\n            child: Text(\'Body $index\'),\n          ),\n        ),\n      ),\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在此输入图像描述

\n
Doctor summary (to see all details, run flutter doctor -v):\n[\xe2\x9c\x93] Flutter (Channel stable, 2.2.3, on macOS 11.5.1 20G80 darwin-x64, locale de-DE)\n[!] Android toolchain - develop for Android devices (Android SDK version 30.0.2)\n    \xe2\x9c\x97 Android license status unknown.\n      Run `flutter doctor --android-licenses` to accept the SDK licenses.\n      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.\n[\xe2\x9c\x93] Xcode - develop for iOS and macOS\n[\xe2\x9c\x93] Chrome - develop for the web\n[\xe2\x9c\x93] Android Studio (version 4.2)\n[\xe2\x9c\x93] IntelliJ IDEA Community Edition (version 2021.1.1)\n[\xe2\x9c\x93] VS Code (version 1.59.0)\n[\xe2\x9c\x93] Connected device (2 available)\n
Run Code Online (Sandbox Code Playgroud)\n

Flo*_*uer 7

看来没有办法避免手动删除填充。所以我的解决方案现在看起来像这样:

return Scaffold(
      body: DefaultTabController(
        length: 2,
        child: NestedScrollView(
          headerSliverBuilder: (context, innerBoxIsScrolled) => [
            SliverAppBar(
              pinned: true,
              title: Text('Title'),
              bottom: TabBar(tabs: [Tab(text: 'T 1'), Tab(text: 'T 2')]),
            ),
          ],
          body: MediaQuery.removePadding(
            removeTop: true,
            context: context,
            child: ListView.builder(
              itemCount: 24,
              itemBuilder: (context, index) => Container(
                height: 40,
                padding: EdgeInsets.zero,
                alignment: Alignment.center,
                color: Colors.yellow,
                margin: EdgeInsets.only(top: index != 0 ? 8 : 0),
                child: Text('Body $index'),
              ),
            ),
          ),
        ),
      ),
    );
Run Code Online (Sandbox Code Playgroud)


Pet*_*tai 6

ListView添加一些默认填充,查看文档

默认情况下,ListView 将自动填充列表的可滚动末端,以避免 MediaQuery 的填充指示的部分阻塞。要避免此行为,请使用零填充属性进行覆盖。

padding您可以通过在构建器中添加配置来轻松摆脱它,如下所示(您可以添加 0 但我不推荐它):

body: ListView.builder(
  padding: const EdgeInsets.only(top: 8), // <-- add this line
  itemCount: 24,
  itemBuilder: (context, index) => Container(
    height: 40,
    alignment: Alignment.center,
    color: Colors.yellow,
    margin: EdgeInsets.only(top: index != 0 ? 8 : 0),
    child: Text('Body $index'),
  ),
),
Run Code Online (Sandbox Code Playgroud)