GotJimmy / accordion

Other
46 stars 43 forks source link

Show / hide an accordion section conditionally without a rebuild #62

Closed atreeon closed 3 months ago

atreeon commented 6 months ago

I recreated a simple version of what has been suggested in #61.

When the state changes in order to conditionally show / hide another panel, the currently open panel closes or opens and closes which doesn't provide a nice experience for the user. Is there currently a way round this?

class AccordionPage extends StatefulWidget {
  _AccordionPageState createState() => _AccordionPageState();
}

class _AccordionPageState extends State<AccordionPage> {
  var myValue = false;

  Widget build(BuildContext context) {
    return Accordion(
      openAndCloseAnimation: false,
      children: [
        AccordionSection(
          header: Text('blah'),
          content: ElevatedButton(onPressed: () => setState(() => myValue = !myValue), child: Text('Set Me')),
        ),
        if (!myValue)
          AccordionSection(
            header: Text('Chart View'),
            content: const Text("Please select a site"),
          )
      ],
    );
  }
}
GotJimmy commented 6 months ago

You're rebuilding the entire Accordion widget through your state. That's why it's playing the opening animation each time. There are some closed issues that address this problem.

atreeon commented 6 months ago

Thanks @GotJimmy I could put the state in the content but that would be too low down and my accordion would still be shown in the list of accordions. If I do this kind of thing it will cause a rebuild of my column but that is fine because it wouldn't trigger any animations and widgets would be reused. Or am I missing something fundamental?!

class MyRebuildPage extends StatefulWidget {
  _MyRebuildPageState createState() => _MyRebuildPageState();
}

class _MyRebuildPageState extends State<MyRebuildPage> {
  var myValue = false;

  Widget build(BuildContext context) {
    return Column(
      children: [
        LayoutBuilder(builder: (x, y) {
          print('rebuilding blahs');
          return const Text('blahs');
        }),
        ElevatedButton(onPressed: () => setState(() => myValue = !myValue), child: Text('Set Me')),
        if (!myValue) //
          Text('Chart View'),
      ],
    );
  }
}
GotJimmy commented 6 months ago

I think making it with a dynamic list at this point (and not playing the opening animations) isn't easy to do at this point. I'll try to fix this in the next major version in the future.