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) {
    ...
  }
}

因此,当您的 itemBuilderListView 中被调用时,它对每个项目使用相同的 _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(() {});
                      },
                    ),
                  ),
                ),
              ]),
            );
          }),
    );
  }
}

结帐Dart's Lexical Scope

首先,您应该删除 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。从长远来看,它将帮助您避免错误和更好的维护