首页 > 解决方案 > 带有 ListView.builder 的 Flutter ExpansionTile 有奇怪的垂直滚动问题

问题描述

我在下面有一个我的问题的例子。当使用 ListView.builder() 懒惰地使用 ExpansionTile() 构建列表中的项目时,我有一个奇怪的行为,我无法通过从打开的扩展磁贴中抓取一个项目来滚动 OVERALL 列表。如果我在列表顶层的基本项目上抓取整个列表,那么我仍然可以滚动整个列表。

我写了一个演示应用程序来展示这一点。

如果您将 bool 标志 swapFailureTrigger 设置为 true,它不会将 ListView.builder() 用于打开的扩展磁贴内容,而只是将其全部放入内存中。然后,无论您在哪里抓取列表,事情都会顺利进行垂直滚动。

如果您将 bool 标志 swapFailureTrigger 设置为 false,那么它会使用 ListView.builder(),您可以通过打开扩展磁贴并尝试通过抓取扩展列表中的项目来垂直滚动来体验失败。

我不确定它是否可能与我正在使用的密钥有关?

import 'package:flutter/material.dart';

// If TRUE, scrolling works well when grabbing an open expansion tile list
// If FALSE, scrolling only works if you grab a parent list OUTSIDE the items of the open expansion tile
bool swapFailureTrigger = false;

class EntryItem extends StatelessWidget {
  const EntryItem(this.entry);

  final Entry entry;

  Widget _buildTiles(Entry root) {
    if (root.children.isEmpty) return ListTile(title: Text(root.title));
    var kids = root.children.map((child) => _buildTiles(child)).toList();

    return ExpansionTile(
      key: PageStorageKey<Entry>(root),
      title: Text(root.title),

      // <<---------- PROBLEM IS HERE if you test with the ListView.builder() version ---------->>
      children: swapFailureTrigger ?
      root.children.map(_buildTiles).toList():
      <Widget>[
        ListView.builder(
          key: PageStorageKey<Entry>(root),
          itemCount: kids.length,
          itemBuilder: (context, index) {
            return kids[index];
          },
          shrinkWrap: true,
        )
      ],
      //  <<--------------------------------------------------------------------------------->>


    );
  }

  @override
  Widget build(BuildContext context) {
    return _buildTiles(entry);
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Expansion Issue'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ExpansionTileExample(),
    );
  }
}

class ExpansionTileExample extends StatelessWidget {
  const ExpansionTileExample({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemBuilder: (BuildContext context, int index) => EntryItem(data[index]),
      itemCount: data.length,
    );
  }
}

// One entry in the multilevel list displayed by this app.
class Entry {
  const Entry(this.title, [this.children = const <Entry>[]]);
  final String title;
  final List<Entry> children;
}

// Data to display.
const List<Entry> data = <Entry>[
  Entry(
    'Chapter A',
    <Entry>[
      Entry(
        'Section A0',
        <Entry>[
          Entry('Item A0.1'),
          Entry('Item A0.2'),
        ],
      ),
      Entry('Section A1'),
      Entry('Section A2'),
      Entry('Section A3'),
      Entry('Section A4'),
      Entry('Section A5'),
      Entry('Section A6'),
      Entry('Section A7'),
      Entry('Section A8'),
      Entry('Section A9'),
      Entry('Section A10'),
      Entry('Section A11'),
      Entry('Section A12'),
      Entry('Section A13'),
      Entry('Section A14'),
      Entry('Section A15'),
      Entry('Section A16'),
      Entry('Section A17'),
      Entry('Section A18'),
      Entry('Section A19'),
    ],
  ),
  Entry(
    'Chapter B',
    <Entry>[
      Entry('Section B1'),
      Entry('Section B2'),
      Entry('Section B3'),
      Entry('Section B4'),
      Entry('Section B5'),
      Entry('Section B6'),
      Entry('Section B7'),
      Entry('Section B8'),
      Entry('Section B9'),
      Entry('Section B10'),
      Entry('Section B11'),
      Entry('Section B12'),
      Entry('Section B13'),
      Entry('Section B14'),
      Entry('Section B15'),
      Entry('Section B16'),
      Entry('Section B17'),
      Entry('Section B18'),
      Entry('Section B19'),
    ],
  ),
  Entry(
    'Chapter C',
    <Entry>[
      Entry('Section C1'),
      Entry('Section C2'),
      Entry('Section C3'),
      Entry('Section C4'),
      Entry('Section C5'),
      Entry('Section C6'),
      Entry('Section C7'),
      Entry('Section C8'),
      Entry('Section C9'),
      Entry('Section C10'),
      Entry('Section C11'),
      Entry('Section C12'),
      Entry('Section C13'),
      Entry('Section C14'),
      Entry('Section C15'),
      Entry('Section C16'),
      Entry('Section C17'),
      Entry('Section C18'),
      Entry('Section C19'),
    ],
  ),
  Entry(
    'Chapter D',
    <Entry>[
      Entry('Section D1'),
      Entry('Section D2'),
      Entry('Section D3'),
      Entry('Section D4'),
      Entry('Section D5'),
      Entry('Section D6'),
      Entry('Section D7'),
      Entry('Section D8'),
      Entry('Section D9'),
      Entry('Section D10'),
      Entry('Section D11'),
      Entry('Section D12'),
      Entry('Section D13'),
      Entry('Section D14'),
      Entry('Section D15'),
      Entry('Section D16'),
      Entry('Section D17'),
      Entry('Section D18'),
      Entry('Section D19'),
    ],
  ),
  Entry(
    'Chapter E',
    <Entry>[
      Entry('Section E1'),
      Entry('Section E2'),
      Entry('Section E3'),
      Entry('Section E4'),
      Entry('Section E5'),
      Entry('Section E6'),
      Entry('Section E7'),
      Entry('Section E8'),
      Entry('Section E9'),
      Entry('Section E10'),
      Entry('Section E11'),
      Entry('Section E12'),
      Entry('Section E13'),
      Entry('Section E14'),
      Entry('Section E15'),
      Entry('Section E16'),
      Entry('Section E17'),
      Entry('Section E18'),
      Entry('Section E19'),
    ],
  ),
];

标签: flutterlistviewscroll

解决方案


Flutter github 向我指出了答案,仅供参考:

如何在 Flutter 中实现嵌套 ListView?

一行修复了它:

 physics: ClampingScrollPhysics(),

在 ListView.builder() 内


推荐阅读