如何同步singlechildscrollview和listview颤动的滚动?

时间:2018-10-16 06:50:19

标签: listview flutter

如何结合singlechildscrollview和listview的滚动?我试图创建一个布局,其中有一个singlechildscrollview,其中包含包装一些小部件和listview的列。如何结合滚动视图和列表视图的滚动控制器。 (即,我希望列表视图仅在其他窗口小部件滚动和不显示时滚动,并且仅在到达列表视图顶部时再次显示。)例如:在instagram应用中,您具有类似用户图像,用户名,关注者计数,关注计数等,然后有一个列表视图列出了用户的帖子。滚动条已连接。我该如何实现??

我想要的

What I Want

我以前的代码

My previous code

实施了安德烈·托科夫斯基的代码后

After Implementing Andrey Turkovsky's Code

3 个答案:

答案 0 :(得分:1)

当嵌套的listview到达顶部时,我可以编写滚动父级的解决方案。这是我代码的一部分-我有2个元素的ListView。第二个是另一个ListView

class _ConferenceScaffoldState extends CommonScaffoldState<ConferenceScaffold> {

    final ScrollController controller = ScrollController();
    final GlobalKey widgetKey = GlobalKey();
    /* widgetKey is for widget in buildHeaderRow() */
    StreamController<bool> _streamController = StreamController<bool>();

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text(conference_title),
          centerTitle: true,
        ),
        body: getBody(),
      );
    }

    Widget getBody() {
    controller.addListener((){
      if (widgetKey.currentContext != null) {
        double height = widgetKey.currentContext.size.height;
        _streamController.add(controller.offset >= height);
      }
    });
      return ListView(
        controller: controller,
        children: <Widget>[buildHeaderRow(), buildPagerRow()],
      );
    }

    Widget buildPagerRow() => _EventSpeakerPager(scrollCallback, _streamController.stream);

    scrollCallback(double position) => controller.position.jumpTo(controller.position.pixels - position);

    @override
    void dispose() {
      controller.dispose();
      super.dispose();
    }
  }

  typedef ScrollCallback = void Function(double position);

  class _EventSpeakerPager extends StatefulWidget {
    _EventSpeakerPager(this.callback, this.stream);

    final ScrollCallback callback;
    final Stream<bool> stream;

    @override
    State<StatefulWidget> createState() => _EventSpeakerPagerState();
  }

  class _EventSpeakerPagerState extends State<_EventSpeakerPager> {
    final GlobalKey tabKey = GlobalKey();
    bool isChildScrollEnabled = false;

  @override
  void initState() {
    super.initState();
    widget.stream.distinct().listen((bool data) {
      setState(() {
        isChildScrollEnabled = data;
      });
    });
  }

    @override
    Widget build(BuildContext context) {
      ListView eventList = ListView.builder(
        physics: isChildScrollEnabled ? AlwaysScrollableScrollPhysics() : NeverScrollableScrollPhysics(),
        controller: ScrollController(),
        itemBuilder: (buildContext, position) {
          if (position.isOdd) return CommonDivider();
          return buildEventRow(getEventList()[position ~/ 2], false, null);
        },
        itemCount: getEventList().length * 2,
      );
      return Listener(
        onPointerMove: (event) {
          double pixels = eventList.controller.position.pixels;
          if (event.delta.dy > 0.0 && pixels == 0.0) widget.callback(event.delta.dy);
        },
        child: ...,
      );
    }
  }

UPD 添加了用于更改带流子的滚动物理的解决方案

答案 1 :(得分:0)

我建立自己的Listview,就像这样:

List<String> myList = ["one", "two", "three", "four"]; //Just some example list data

ListView.builder(,
    itemCount: myList.length,
    itemBuilder: (BuildContext context, int index) {
        return TileWidget(
              myList[index],              
              index == 0, //this indicates that it is the first item
              index == myList.length - 1); //this indicates that it is the last item
        },
    ),

然后像这样构建我的“ TileWidget”:

class TileWidget extends StatelessWidget {
  TileWidget(this.tileData,  this.isFirstItem, this.isLastItem,);
  String tileData;
  bool isFirstItem;
  bool isLastItem;  

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        isFirstItem ? Text("this is a title") : Container(),
        Text(tileData),
        isLastItem ? Text("This is a footer") : Container(),
      ],
    );
  }
}

不是很漂亮。但这很简单并且有效。

答案 2 :(得分:0)

这可能有点晚了,但是您可以像这样将 NeverScrollableScrollPhysics() 添加到 ListView 的物理参数:

document.getElementsByClassName('chat incoming').length