Listview.builder的builditem函数内的Flutter Setstate无法重新加载 [英] Flutter Setstate inside Listview.builder's builditem function not reloading

查看:547
本文介绍了Listview.builder的builditem函数内的Flutter Setstate无法重新加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个从firestore加载信息的streambuilder.然后,我使用listview.builder来显示信息.显示的信息由函数firstBuildItem或buildItem调用.

I have a streambuilder that loads information from firestore. Then I use a listview.builder to display the information. The displayed information is being called by the function firstBuildItem or buildItem.

我想要的功能是,当用户单击用手势检测器包装的容器时,我希望另一个小部件在主小部件下方展开.我不确定如何用flutter实现此目的,因为由于每个消息都是listview.builder内部的项目,因此布尔值必须在函数内部,因为每个函数都有自己的布尔值,用于检查是否单击了列表项.我想了解如何修正我的代码,以便在列表视图中通过展开单击时每个项目都能响应.

The functionality that I want is that when the user clicks on the container that is wrapped with a gesturedetector, I want another widget to be expanded below the main widget. I'm not sure how to achieve this with flutter because since each message is an item insider listview.builder, the boolean value needs to be local inside the function since every function has its own boolean that is checking for if the list item was clicked. I would like to find out how to fix my code so that each item responds when clicked inside the listview by expanding.

ListView.builder(
padding: EdgeInsets.all(10.0),
itemBuilder: (context, index) =>
index == 0 ? firstBuildItem(index, snapshot.data.documents[index]) : buildItem(index, snapshot.data.documents[index], snapshot.data.documents[index-1]),
itemCount: snapshot.data.documents.length,
reverse: true,
controller: listScrollController,
),

然后是builditem函数:

then here is the builditem function:

Widget firstBuildItem(int index, DocumentSnapshot mainDocument) {

  ///If the box is expanded
  bool _isExpanded = false;

  ///Toggle the box to expand or collapse
  void _toggleExpand() {
    setState(() {
      _isExpanded = !_isExpanded;
    });
  }


  return GestureDetector(

    onTap: _toggleExpand,

    child: Container(

      color: _isExpanded ? Colors.blueGrey : null,

      child: Column(


        children: <Widget>[

          Column(
            children: <Widget>[

              SizedBox(height: 20.0),

              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[

                  ChatDateHeader(timestamp: mainDocument['timestamp']),

                ],
              ),
            ],
          ),

          Column(

            children: <Widget>[

              Row(
                children: <Widget>[
                  Container(
                    child: Text(
                      mainDocument['content'],
                      style: TextStyle(color: primaryColor),
                    ),
                    padding: EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 10.0),

                  ),
                ],
                mainAxisAlignment: MainAxisAlignment.end,
              ),

              getTime(mainDocument['timestamp'], true),

              ExpandedSection(
                expand: _isExpanded,
                child: getDate(mainDocument['timestamp'], true),
              ),

              SizedBox(height: 20.0),

            ],
            crossAxisAlignment: CrossAxisAlignment.end,
          ),
        ],
      ),
    ),
  );
}

,然后展开小部件:

class ExpandedSection extends StatefulWidget {

  final Widget child;
  final bool expand;
  ExpandedSection({this.expand = false, this.child});

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

class _ExpandedSectionState extends State<ExpandedSection> with SingleTickerProviderStateMixin {
  AnimationController expandController;
  Animation<double> animation;

  @override
  void initState() {
    super.initState();
    prepareAnimations();
  }

  ///Setting up the animation
  void prepareAnimations() {
    expandController = AnimationController(
        vsync: this,
        duration: Duration(milliseconds: 500)
    );
    Animation curve = CurvedAnimation(
      parent: expandController,
      curve: Curves.fastOutSlowIn,
    );
    animation = Tween(begin: 0.0, end: 1.0).animate(curve)
      ..addListener(() {
        setState(() {

        });
      }
      );
  }

  @override
  void didUpdateWidget(ExpandedSection oldWidget) {
    super.didUpdateWidget(oldWidget);
    if(widget.expand) {
      expandController.forward();
    }
    else {
      expandController.reverse();
    }
  }

  @override
  void dispose() {
    expandController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SizeTransition(
        axisAlignment: 1.0,
        sizeFactor: animation,
        child: widget.child
    );
  }
}

推荐答案

我通过将firstBuildItem窗口小部件功能转换为它自己的类的有状态窗口小部件来解决了该问题.然后将一个键传递给该函数.这样,setState可以工作,而无需重建整个streambuilder.

I solved the issue by turning firstBuildItem widget function into a stateful widget of it's own class. And then passing a key to the function. With this, setState worked without rebuilding the entire streambuilder.

ListView.builder(
                  padding:    EdgeInsets.all(10.0),
                  itemCount:  snapshot.data.documents.length,
                  reverse:    true,
                  controller: listScrollController,
                  itemBuilder: (context, index) =>

                    index == snapLength ?

                    FirstChatBuildMessageItem(
                      key:          Key('counter-${index}'),
                      id:           id,
                      peerAvatar:   peerAvatar,
                      index:        index,
                      mainDocument: snapshot.data.documents[index],
                      listMessage: listMessage,
                    )
                        :

                    //index == 0 ?

                    ChatBuildMessageItem(
                      key:              Key('counter-${index}'),
                      id:               id,
                      peerAvatar:       peerAvatar,
                      index:            index,
                      mainDocument:     snapshot.data.documents[index],
                      previousDocument: snapshot.data.documents[index + 1],
                      listMessage:      listMessage,
                    ),

                ),

这篇关于Listview.builder的builditem函数内的Flutter Setstate无法重新加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆