首页 > 解决方案 > 在另一个可滚动视图后面传递的可滚动视图

问题描述

我有一个布局,其中有两个滚动视图,一个PageView是用于水平显示图片列表的 a,第二个是 a SingleChildScrollView(也许应该是别的东西?),此滚动视图部分位于第一个视图上方作为初始位置并且可以完全过去。一些截图来描绘这个:

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

问题是,如果我让第二个滚动视图占据所有页面并为其添加内部填充以使其具有良好的高度,则第二个滚动视图按预期工作,但第一个滚动视图(女巫在后面)不再工作了。第二种解决方案是SingleChildScrollView用一个Padding小部件包装它以使其具有良好的高度并向滚动视图添加参数,但在这种情况下,即使结束Clip.none,滚动视图也无法在区域中滚动。PageViewSingleChildScrollView

我想知道是否有人已经遇到过这样的行为,你的解决方案是什么。

这是我的第二个解决方案的实际代码:

  Widget body() {
    return LayoutBuilder(
      builder: (context, boxConstraints) {
        this.boxConstraints = boxConstraints;
        uiHeight = boxConstraints.maxHeight -
            boxConstraints.maxWidth * 9 / 16 +
            scrollableUIBorderRadius;
        return Stack(
          children: [
            coverWidget(),
            scrollableUI(),
          ],
        );
      },
    );
  }

  Widget coverWidget() { //This is the PageView containing pictures
    return Positioned.fill(
        bottom: uiHeight - scrollableUIBorderRadius,
        child: global.coverWidget(
          placeId: widget.place.id,
          galleryItemsLinks: widget.galleryItemsLinks!,
          initialIndex: widget.coverIndex,
          onIndexUpdate: widget.onUpdateIndex,
          circleIndicatorsDistanceFromBottom:
              (boxConstraints.maxHeight - uiHeight) / 15 +
                  scrollableUIBorderRadius,
        ));
  }

  Widget scrollableUI() {
    return Positioned.fill(
      top: boxConstraints.maxHeight - uiHeight,
      child: SingleChildScrollView(
        clipBehavior: Clip.none,
        controller: _scrollController,
        physics: AlwaysScrollableScrollPhysics(parent: BouncingScrollPhysics()),
        scrollDirection: Axis.vertical,
        child: SizedBox(
          height: uiHeight * 2,
          child: Stack(
            children: [
              Positioned.fill(
                child: global.containerWidget(
                  placeId: widget.place.id,
                  borderRadius: BorderRadius.only(
                      topLeft: Radius.circular(scrollableUIBorderRadius),
                      topRight: Radius.circular(scrollableUIBorderRadius)),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

注意:如果可能的话,我想BouncingScrollPhysics轻松保存它们,所以使用AnimationBuilder&& Transform&&的解决方案GestureDetector是最后的手段。

标签: flutterflutter-layout

解决方案


我发现了一个小技巧来做到这一点,我在PageView里面传递了包含照片的东西,SingleChildScrollView所以PageView它在顶部并且可以接收触摸事件,为了保持PageView固定在屏幕顶部,我使用了一个Transform反转scrollOffset.SingleChildScrollView

我的实现:

(此处Transform小部件还用于在小于 0PageView时调整包含照片的大小scrollOffset

[...]

late ScrollController _scrollController = ScrollController()
    ..addListener(_scrollListener);
double _scrollOffset = 0.0;

[...]

_scrollListener() {
    setState(() {
      _scrollOffset = _scrollController.offset;
    });
}

[...]

Widget body() {
    return LayoutBuilder(builder: (context, boxConstraints) {
      this.boxConstraints = boxConstraints;
      coverHeight = boxConstraints.maxWidth * 9 / 16;
      return SingleChildScrollView(
        physics: AlwaysScrollableScrollPhysics(parent: BouncingScrollPhysics()),
        controller: _scrollController,
        child: Column(
          children: [
            Transform(
              transform: Matrix4.compose(
                  vector.Vector3(
                      _scrollOffset > 0 ? 0 : _scrollOffset, _scrollOffset, 0),
                  vector.Quaternion.euler(0.0, 0.0, 0.0),
                  vector.Vector3(
                      _scrollOffset > 0
                          ? 1.0
                          : 1.0 - _scrollOffset / boxConstraints.maxHeight * 4,
                      _scrollOffset > 0
                          ? 1.0
                          : 1.0 - _scrollOffset / boxConstraints.maxHeight * 4,
                      1.0)),
              child: SizedBox(
                height: coverHeight,
                child: global.coverWidget(
                  placeId: widget.place.id,
                  galleryItemsLinks: widget.galleryItemsLinks!,
                  initialIndex: widget.coverIndex,
                  onIndexUpdate: widget.onUpdateIndex,
                  circleIndicatorsDistanceFromBottom:
                      coverHeight / 15 + scrollableUIBorderRadius,
                ),
              ),
            ),
            Stack(
              clipBehavior: Clip.none,
              children: [
                Positioned.fill(
                  top: -scrollableUIBorderRadius,
                  child: global.containerWidget(
                    placeId: widget.place.id,
                    borderRadius: BorderRadius.only(
                        topLeft: Radius.circular(scrollableUIBorderRadius),
                        topRight: Radius.circular(scrollableUIBorderRadius)),
                  ),
                ),
                Column(
                  children: [
                    [...]
                  ],
                ),
              ],
            ),
          ],
        ),
      );
    });
  }

推荐阅读