当某些其他小部件在其上方颤动时,如何防止呈现给定小部件?

时间:2019-06-03 08:28:55

标签: list flutter header widget rendering

我想将列表标题作为粘性标题。给定标题的背景应该是透明的,并且在滚动列表元素“下方”时,标题应该消失,用户应该在列表视图后面看到背景图像。

我正在使用sticky_headers包来获得粘性标头效果。但是我只是从颤抖着开始冒险,对小部件的渲染一无所知。

1 个答案:

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