我想将列表标题作为粘性标题。给定标题的背景应该是透明的,并且在滚动列表元素“下方”时,标题应该消失,用户应该在列表视图后面看到背景图像。
我正在使用sticky_headers包来获得粘性标头效果。但是我只是从颤抖着开始冒险,对小部件的渲染一无所知。
答案 0 :(得分:0)
我设法使用ShaderMask完成了此任务。我的想法是,我计算列表项中的标题在哪里,并将这一部分屏蔽掉。
列表小部件的关键部分是这样:
@override
Widget build(BuildContext context) => ListView.builder(
padding: _padding, itemCount: _sectionCount, itemBuilder: _sectionHeader);
StickyHeader _sectionHeader(BuildContext context, int sectionIndex) {
final GlobalKey eventListHeaderKey = GlobalKey();
final GlobalKey shaderMaskKey = GlobalKey();
final AppStyle appStyle = AppStyle.of(context);
return StickyHeader(
header: Container(
key: eventListHeaderKey,
child: _sectionHeaderBuilder(context, sectionIndex)),
content: ShaderMask(
key: shaderMaskKey,
shaderCallback: (Rect rect) =>
_listShader(appStyle, eventListHeaderKey, shaderMaskKey, rect),
blendMode: BlendMode.dstIn,
child: Container(
child: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: _sectionElementsCountHandler(sectionIndex),
itemBuilder: (BuildContext context, int index) =>
_elementBuilder(context, sectionIndex, index)))));
}
Shader _listShader(AppStyle appStyle, GlobalKey listHeaderKey,
GlobalKey shaderMaskKey, Rect rect) {
final RenderBox listHeaderRenderBox =
listHeaderKey.currentContext.findRenderObject();
final Offset offset = listHeaderRenderBox.localToGlobal(Offset.zero);
final RenderBox shaderMaskRenderBox =
shaderMaskKey.currentContext.findRenderObject();
final Offset offset2 = shaderMaskRenderBox.globalToLocal(offset);
return LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: <double>[
0,
(rect.top + offset2.dy) / rect.height,
(rect.top + offset2.dy) / rect.height,
1
],
colors: <Color>[
appStyle.colors.transparent,
appStyle.colors.transparent,
appStyle.colors.white,
appStyle.colors.white
]).createShader(Rect.fromLTWH(0, 0, rect.width, rect.height));
}