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
CodePudding user response:
The problem is that you're using the same _expanded variable for items in your ListView.
class _NovalsState extends State<Novals> {
bool _expanded = false;
...
@override
Widget build(BuildContext context) {
...
}
}
So when your itemBuilder is called in the ListView, it uses the same _expanded value for every item.
Solution:
Move the _expanded variable from the State to inside the body itemBuilder function.
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) {
bool _expanded = false;
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(() {});
},
),
),
),
]),
);
}),
);
}
}
Checkout Dart's Lexical Scope
CodePudding user response:
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
