flutter 扩展面板 listView Builder
flutter expansion panel listView Builder
一个领域的初学者,我有这个代码可以运行,但是在点击的情况下出现错误
当我点击任何卡片时,所有卡片也会打开。我想打开一张我只需点击的卡片
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(() {
});
},
),
),
),
]
),
);
}
),
);
}
}
我尝试解决了,但是我无法让代码显示故事名称,当用户点击它时,整个故事出现
问题是您对 ListView
中的项目使用相同的 _expanded
变量。
class _NovalsState extends State<Novals> {
bool _expanded = false;
...
@override
Widget build(BuildContext context) {
...
}
}
因此,当您的 itemBuilder
在 ListView
中被调用时,它对每个项目使用相同的 _expanded
值。
解法:
将 _expanded
变量从 State
移动到主体 itemBuilder
函数内部。
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(() {});
},
),
),
),
]),
);
}),
);
}
}
首先,您应该删除 SingleChildScrollView
作为 ListView
child。 ListView.builder
足以滚动到您的 Scaffold
。
对于主要问题,您应该将每个项目拆分为一个单独的 Widget
并具有自己的 _expanded
状态。这将使您的 UI 更快,小部件将单独展开并且整个屏幕将不必在每个项目的 setState()
.
之后重新加载
示例代码:
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:最好使用 jsonDecode()
将 story
放入模型 class 而不是直接使用 Map
。从长远来看,它将帮助您避免错误和更好的维护
一个领域的初学者,我有这个代码可以运行,但是在点击的情况下出现错误 当我点击任何卡片时,所有卡片也会打开。我想打开一张我只需点击的卡片
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(() {
});
},
),
),
),
]
),
);
}
),
);
}
}
我尝试解决了,但是我无法让代码显示故事名称,当用户点击它时,整个故事出现
问题是您对 ListView
中的项目使用相同的 _expanded
变量。
class _NovalsState extends State<Novals> {
bool _expanded = false;
...
@override
Widget build(BuildContext context) {
...
}
}
因此,当您的 itemBuilder
在 ListView
中被调用时,它对每个项目使用相同的 _expanded
值。
解法:
将 _expanded
变量从 State
移动到主体 itemBuilder
函数内部。
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(() {});
},
),
),
),
]),
);
}),
);
}
}
首先,您应该删除 SingleChildScrollView
作为 ListView
child。 ListView.builder
足以滚动到您的 Scaffold
。
对于主要问题,您应该将每个项目拆分为一个单独的 Widget
并具有自己的 _expanded
状态。这将使您的 UI 更快,小部件将单独展开并且整个屏幕将不必在每个项目的 setState()
.
示例代码:
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:最好使用 jsonDecode()
将 story
放入模型 class 而不是直接使用 Map
。从长远来看,它将帮助您避免错误和更好的维护