flutter expansion panel listView Builder

Issue

a beginner in a field, I have this code that works, but there is an error in the case of clicking
When I click on any card, all cards also open. I want to open a card that I just click on

import 'dart:io';
import 'package:english_club/data/im.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';


class Novals extends StatefulWidget {
  @override
  _NovalsState createState()
  {
    return _NovalsState();
  }
}

class _NovalsState extends State<Novals> {
  bool _expanded = false;
  var _test = "Full Screen";
  @override
  Widget build(BuildContext context) {
    return Scaffold(
       resizeToAvoidBottomInset: false,
      body: ListView.builder(
        itemCount: storys.length,

        itemBuilder: (context, index){
          return SingleChildScrollView(
            child: Column(
              children: [
                Center(
                  child: Container(
                    margin: EdgeInsets.all(10),
                    color: Colors.green,
                    child: ExpansionPanelList(
                    animationDuration: Duration(milliseconds: 2000),
                    children: [
                      ExpansionPanel(
                          headerBuilder: (context, isExpanded) {
                            return ListTile(
                              title: Text(storys[index]["name"], style: TextStyle(color: Colors.black),),
                            );
                          },
                          body:ListTile(
                            title: Text(storys[index]["lines"],style: TextStyle(color: Colors.black)),
                          ),
                        isExpanded: _expanded,
                        canTapOnHeader: true,
                      ),
                    ],
                    dividerColor: Colors.grey,
                    expansionCallback: (panelIndex, isExpanded) {
                      _expanded = !_expanded;
                      setState(() {

                      });
                    },

              ),
             ),
                ),
            ]
            ),
          );
        }
      ),
    );
  }
}

I tried to solve it, but I could not aim for the code to display the name of the story, and when the user clicks on it, the whole story appears

Solution

Firstly, you should remove the SingleChildScrollView as the ListView child. ListView.builder is enough to provide scrolling to your Scaffold.

For the main issue, you should split each item to a separate Widget with its own _expanded state. This will make your UI much faster, the widgets will expand separately and the whole screen won’t have to reload after each item’s setState().

Example code:

class Novals extends StatefulWidget {
  @override
  _NovalsState createState()
  {
    return _NovalsState();
  }
}

class _NovalsState extends State<Novals> {
  var _test = "Full Screen";
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: ListView.builder(
          itemCount: storys.length,
          itemBuilder: (context, index){
            return StoryWidget(story: storys[index]);
          }
      ),
    );
  }
}

class StoryWidget extends StatefulWidget {
  final Map<String, dynamic> story;
  const StoryWidget({Key? key, required this.story}) : super(key: key);

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

class _StoryWidgetState extends State<StoryWidget> {  
bool _expanded = false;

@override
  Widget build(BuildContext context) {
    return Column(
        children: [
          Center(
            child: Container(
              margin: EdgeInsets.all(10),
              color: Colors.green,
              child: ExpansionPanelList(
                animationDuration: Duration(milliseconds: 2000),
                children: [
                  ExpansionPanel(
                    headerBuilder: (context, isExpanded) {
                      return ListTile(
                        title: Text(widget.story["name"], style: TextStyle(color: Colors.black),),
                      );
                    },
                    body:ListTile(
                      title: Text(widget.story["lines"],style: TextStyle(color: Colors.black)),
                    ),
                    isExpanded: _expanded,
                    canTapOnHeader: true,
                  ),
                ],
                dividerColor: Colors.grey,
                expansionCallback: (panelIndex, isExpanded) {
                  _expanded = !_expanded;
                  setState(() {});
                },
              ),
            ),
          ),
        ]
    );
  }
}

P/s: It’s a good practice to put your story into a model class using jsonDecode() instead of using Map directly. It would help you avoid bugs and better maintenance in the long term

Answered By – Bach

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published