与ScrollController的嵌套ListView不滚动

时间:2020-08-17 10:32:14

标签: flutter listview nested scrollcontroller

我正在构建一个带有自定义导航栏的小部件,其中包括一个Stack,其主体和导航栏。

@override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        _buildBody(),
        _buildNavigationBar(),
      ],
    );
  }

正文由ListView(带有标题)和嵌套在内容下面的ListView.builder组成。

Widget _buildBody() {
    return ListView(
      padding: EdgeInsets.only(top: 44.0 + MediaQuery.of(context).padding.top),
      controller: _scrollController,
      children: [
        Opacity(
          opacity: 1.0 - _navigationBarOpacity,
          child: Padding(
            padding: const EdgeInsets.only(bottom: 15.0),
            child: _buildHeaderTitle(
              title: widget.title,
              fontSize: _largeFontSize,
              fontWeight: _largeFontWeight,
              color: widget.color,
            ),
          ),
        ),
        ListView.builder(
          padding: EdgeInsets.zero,
          shrinkWrap: true,
          physics: NeverScrollableScrollPhysics(),
          itemCount: widget.itemCount,
          itemBuilder: (context, index) {
            return widget.itemBuilder(context, index);
          },
        ),
      ],
    );
  }

我正在主/根ScrollController上使用ListView,以淡入和淡出导航栏。这可以按预期工作。

但是,ScrollController添加到ListView会停止任何滚动/弹跳交互。我该如何解决?

ScrollController _scrollController = ScrollController();

@override
  void initState() {
    super.initState();

    _scrollController.addListener(() {
      setState(() {
        double min = 0.0;
        double max = 25.0;
        _navigationBarOpacity = (_scrollController.offset - min) / (max - min);
        if (_navigationBarOpacity < 0) _navigationBarOpacity = 0;
        if (_navigationBarOpacity > 1) _navigationBarOpacity = 1;
      });
    });  
  }

有趣的是,如果我将ScrollController移到nestedt ListView.builder上,则根ListView会滚动/跳动,但是我无法再基于偏移量调整UI因为它在错误的ListView上。

另一个有趣的问题是,如果根ListView的子级超过其高度,则正常滚动。但是,在某些情况下它并没有它,我希望它只是在拉动时反弹。


更新

即使我删除堆栈并嵌套ListView,带有ListView的简单单数ScrollController也不会在拖动时滚动,没有它,它将拖动。这是需要解决的根本问题。

@override
  Widget build(BuildContext context) {
    return ListView(
        padding: EdgeInsets.only(top: 44.0 + MediaQuery.of(context).padding.top),
        controller: _scrollController,
        children: [
          Opacity(
            opacity: 1.0 - _navigationBarOpacity,
            child: Padding(
              padding: const EdgeInsets.only(bottom: 15.0),
              child: _buildHeaderTitle(
                title: widget.title,
                fontSize: _largeFontSize,
                fontWeight: _largeFontWeight,
                color: widget.color,
              ),
            ),
          ),
        ],
      );
  }

1 个答案:

答案 0 :(得分:0)

通过将父项ListView包裹在PrimaryScrollController中,然后在primary = true上设置ListView来解决。

这使PrimaryScrollController管理控制器,但是ListView保持了典型的滚动行为,因为它不再管理ScrollController

请参阅Flutter文档:https://api.flutter.dev/flutter/widgets/ScrollView/primary.html