将 slivers 添加到反向 CustomScrollView 或 ListView 时,将 sticky headers 固定在顶部
Pin sticky headers on top when adding slivers to a reverse CustomScrollView or ListView
我正在实现一个聊天小部件并使用 https://github.com/letsar/flutter_sticky_header 库按日期分隔消息,您可以在 Whatsapp 和 Telegram 上看到相同的行为。
我正在构建几个 slivers
,每个都包含该日期的消息和一个 header,它基本上是一个显示相关日期的文本。我将 slivers
传递给 CustomScrollView
,reverse
属性 设置为 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)),
);
}
除了 header 固定在屏幕底部(我需要它们固定在顶部)外,一切正常。
我怎样才能解决这个问题?任何指针将不胜感激。
看起来这个插件有问题,其他开发者已经发现了它
否则,我会使用现有的小部件重新实现 sliverlist,
可能是 SliverList 和 SliverPersistentHeader
的组合
好的,我去别处回答了,我在这里提交以供将来参考:
尝试使用不同的库 (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,
)
)
]
)
);
然后在构建函数中:
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,
);
很适合我!
我正在实现一个聊天小部件并使用 https://github.com/letsar/flutter_sticky_header 库按日期分隔消息,您可以在 Whatsapp 和 Telegram 上看到相同的行为。
我正在构建几个 slivers
,每个都包含该日期的消息和一个 header,它基本上是一个显示相关日期的文本。我将 slivers
传递给 CustomScrollView
,reverse
属性 设置为 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)),
);
}
除了 header 固定在屏幕底部(我需要它们固定在顶部)外,一切正常。 我怎样才能解决这个问题?任何指针将不胜感激。
看起来这个插件有问题,其他开发者已经发现了它
否则,我会使用现有的小部件重新实现 sliverlist, 可能是 SliverList 和 SliverPersistentHeader
的组合好的,我去别处回答了,我在这里提交以供将来参考:
尝试使用不同的库 (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,
)
)
]
)
);
然后在构建函数中:
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,
);
很适合我!