skip to Main Content

I am implementing a chat widget and using https://github.com/letsar/flutter_sticky_header library to separate messages by date, you can see the same behavior on Whatsapp and Telegram.

I am building several slivers that each contain messages on that date and a header which is basically a text showing the relevant date. I pass the slivers to a CustomScrollView with reverse property set to true.

 return CustomScrollView(
      slivers: _buildListItem(context, sectionIndex),
      reverse: true,
      controller: listScrollController,
    );
  List<Widget> _buildListItem(
    BuildContext context,
    List<ChatSection> chatSections,
  ) {
    List<Widget> slivers = List();
    chatSections.forEach((chatSection) {
      slivers.add(_buildChatSliver(
          context, chatSection.messages, chatSection.datetime));
    });

    return slivers;
  }
  SliverStickyHeaderBuilder _buildChatSliver(BuildContext context,
      List<ChatMessage> chatMessages, DateTime dateTimeHeader) {
    return SliverStickyHeaderBuilder(
      overlapsContent: false,
      builder: (context, state) {
        DateTime now = DateTime.now();
        String headerText = now.year != dateTimeHeader.year
            ? DateFormat("YYYY MMM dd").format(dateTimeHeader)
            : DateFormat("MMM dd").format(dateTimeHeader);
        return Container(
          padding: EdgeInsets.fromLTRB(5, 0, 15, 5),
          child: Center(
            child: Container(
              padding: EdgeInsets.fromLTRB(5, 5, 5, 5),
              decoration: BoxDecoration(
                  color: Color.fromARGB(200, 150, 150, 150),
                  borderRadius: BorderRadius.all(Radius.circular(5))),
              child: Text(
                headerText,
                style: TextStyle(
                    color: Colors.white70,
                    fontSize: 12.0,
                    fontStyle: FontStyle.italic),
              ),
            ),
          ),
        );
      },
      sliver: SliverList(
          delegate: SliverChildBuilderDelegate(
              (context, i) => _buildItem(chatMessages[i]),
              childCount: chatMessages.length)),
    );
  }

Everything works fine except that the headers are pinned to the bottom of the screen (I need them to stick to the top).
How can I fix this? Any pointers would be appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    Okay, I go my answer somewhere else and I am submitting it here for future reference:

    try using different library (https://pub.dev/packages/sticky_headers).

    return StickyHeader(
      header: _sectionHeader(dateText),
      content: Column(
        children: <Widget>[
          if (isLast) _topWidget(),
          for (var i in list.reversed)
            ListTile(
              title: ChatMessageWidget(
                message: i,
                senderUuid: widget.senderUuid,
                key: Key('chatmsg$key$i'),
                onLongPress: _onMsgPressed,
                onTap: _onMsgPressed,
              )
            )
        ]
      )
    );
    

    and then in build function:

    return CustomScrollView(
      key: Key('MessagesList'),
      controller: _scrollController,
      slivers: <Widget>[
        SliverList(delegate: SliverChildBuilderDelegate((context, index) {
          if (index == 0) {
            return _bottomView();
          } else {
            final key = keys[index - 1];
            return _buildSection(context, key, mapped[key], index == keys.length);
          }
        },
        childCount: keys.length + 1)),
      ],
      reverse: true,
    );
    

    works well for me!


  2. looks like theres an issue with this plugin and other devs have picked up on it

    Reverse list support

    otherwise, I would reimplement the sliverlist using existing widgets,
    maybe a combination of SliverList and SliverPersistentHeader

    SliverPersistentHeader Class

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search