Flutter Setstate внутри функции builditem Listview.builder не перезагружается - PullRequest
0 голосов
/ 10 апреля 2020

У меня есть streambuilder, который загружает информацию из пожарного хранилища. Затем я использую listview.builder для отображения информации. Отображаемая информация вызывается функцией firstBuildItem или buildItem.

Функциональность, которую я хочу, заключается в том, что когда пользователь нажимает на контейнер, обернутый детектором жестов, я хочу, чтобы другой виджет был развернут ниже основного виджета. Я не уверен, как этого добиться с помощью flutter, потому что, поскольку каждое сообщение является внутренним элементом listview.builder, логическое значение должно быть локальным внутри функции, поскольку каждая функция имеет свой логический параметр, который проверяет, был ли выбран элемент списка. , Я хотел бы выяснить, как исправить мой код, чтобы каждый элемент реагировал на щелчок внутри просмотра списка путем расширения.

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:

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
    );
  }
}

1 Ответ

0 голосов
/ 11 апреля 2020

Я решил проблему, превратив функцию виджета firstBuildItem в виджет с сохранением состояния своего собственного класса. А затем передать ключ к функции. При этом setState работал без перестройки всего потокового построителя.

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,
                    ),

                ),
...