当有大量子项时,展开ExpansionTile时出现卡顿现象。

4

你好!

一切都在标题中。

我有一个扩展瓷砖,用于显示一个组的成员。当有很多人在一个组中(这里是47),扩展就不流畅了,它只是闪烁并打开。

在处理许多子项时,有没有办法使动画更加平滑?

提前感谢!


1
我也遇到了同样的问题,这个问题应该得到更多的关注。需要像ListView这样的东西,只在需要时渲染子元素。 - Extreme Geek
2个回答

1

我意识到的原因是,当您展开一个面板时,所有子面板都会触发setState。以下是我的解决方案。我制作了自己的扩展面板,这样当一个setstate被触发时,它不会影响整个面板。对于我来说,它更加流畅。请注意在何处以及如何调用setstate。Column小部件可以成为模板,并在ListView中使用。

class TestPage extends StatefulWidget {
  const TestPage({Key? key}) : super(key: key);

  @override
  _TestPageState createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {

  bool isExpanded = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: ListView(
          children: [
            Column(
              children: [
                ListTile(
                  onTap: () {
                    setState(() => isExpanded = !isExpanded);
                  },
                  title: Text('Title widget'),
                ),
                AnimatedSize(
                  duration: Duration(milliseconds: 250),
                  curve: Curves.fastOutSlowIn,
                  child: AnimatedCrossFade(
                    firstChild: Container(height: 0.0),
                    secondChild: Column(
                      children: [
                        Text('widget 1'),
                        Text('widget 2'),
                        Text('widget 3'),
                        Text('widget 4'),
                        Text('widget 5'),
                      ],
                    ),
                    firstCurve:
                        const Interval(0.0, 0.6, curve: Curves.fastOutSlowIn),
                    secondCurve:
                        const Interval(0.4, 1.0, curve: Curves.fastOutSlowIn),
                    sizeCurve: Curves.fastOutSlowIn,
                    crossFadeState: isExpanded
                        ? CrossFadeState.showSecond
                        : CrossFadeState.showFirst,
                    duration: Duration(milliseconds: 250),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

0
刚刚在@BananaMaster的回答基础上进行了一点小修改,新增了一个箭头和一些阴影效果,使整个面板看起来更像原始的ExpansionPanel。
class TestPage extends StatefulWidget {
  const TestPage({Key? key}) : super(key: key);

  @override
  _TestPageState createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {

  bool isExpanded = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: ListView(
          children: [
            Column(
              children: [
                ListTile(
                  onTap: () {
                    setState(() => isExpanded = !isExpanded);
                  },
                  leading: const Text(
                    'Title goes here',
                    style: TextStyle(fontSize: 17),
                  ),
                  title: Align(
                    child: isExpanded == true
                        ? const Icon(Icons.arrow_drop_up)
                        : const Icon(Icons.arrow_drop_down),
                    alignment: Alignment.centerRight,
                  ),
                  margin: const EdgeInsets.all(5),
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: const BorderRadius.only(
                        topLeft: Radius.circular(5),
                        topRight: Radius.circular(5),
                        bottomLeft: Radius.circular(5),
                        bottomRight: Radius.circular(5)),
                    boxShadow: [
                      BoxShadow(
                        color: Colors.grey.withOpacity(0.5),
                        spreadRadius: 1,
                        blurRadius: 1,
                        offset:
                            const Offset(0, 1),
                      ),
                    ],
                  ),
                ),
                AnimatedSize(
                  duration: Duration(milliseconds: 250),
                  curve: Curves.fastOutSlowIn,
                  child: AnimatedCrossFade(
                    firstChild: Container(height: 0.0),
                    secondChild: Column(
                      children: [
                        Text('widget 1'),
                        Text('widget 2'),
                        Text('widget 3'),
                        Text('widget 4'),
                        Text('widget 5'),
                      ],
                    ),
                    firstCurve:
                        const Interval(0.0, 0.6, curve: Curves.fastOutSlowIn),
                    secondCurve:
                        const Interval(0.4, 1.0, curve: Curves.fastOutSlowIn),
                    sizeCurve: Curves.fastOutSlowIn,
                    crossFadeState: isExpanded
                        ? CrossFadeState.showSecond
                        : CrossFadeState.showFirst,
                    duration: Duration(milliseconds: 250),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接