flutteroptimizationlagtileexpansion

ExpansionTile lagging when expanding with a lot of children


Hello !

Everything is in the title.

I have an expansion tile to show members of a group. When lots of people are in a group (here 47), the expansion is not smooth at all and it simply blinks and opens.

Is there a way to make the animation smoother when dealing with a lot of children ?

Thanks in advance !


Solution

  • I realized the reason is that when you expand one panel setState is triggered for all children. Here's my solution. I made my own expansion panel so that when one setstate is triggered it doesn't affect the whole thing. It works smoother for me. Be careful where and how you call setstate. The Column widget can become a template and used in a 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),
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        );
      }
    }