简体   繁体   English

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

[英]how to sync scroll of singlechildscrollview and listview flutter?

How to combine scroll of singlechildscrollview and listview?如何结合singlechildscrollview和listview的滚动? I am trying to create a layout in which there is a singlechildscrollview containing column which wraps some widgets and a listview.我正在尝试创建一个布局,其中有一个包含包含一些小部件和列表视图的列的 singlechildscrollview。 How do I combine the scroll controller of the scroll view and the listview.如何组合滚动视图和列表视图的滚动控制器。 (ie I want the listview to scroll only when the other widgets are scrolled out and out of display and again show only when the listview is reached top.) For instance: in instagram app you have the widgets like userimage, username, followers count, following count, etc and then there is a listview listing the posts of the user. (即,我希望列表视图仅在其他小部件滚动出并退出显示时才滚动,并且仅在列表视图到达顶部时再次显示。)例如:在 Instagram 应用程序中,您有用户图像、用户名、关注者计数等小部件,跟随计数等,然后有一个列表视图列出用户的帖子。 The scroll is connected.卷轴已连接。 How do i achieve this???我如何实现这个???

What I Want我想要的是

我想要的是

My previous code我之前的代码

我之前的代码

After Implementing Andrey Turkovsky's Code实施安德烈·特科夫斯基的代码后

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

I can write solution for scrolling parent when nested listview is reaches top.当嵌套列表视图到达顶部时,我可以编写滚动父级的解决方案。 Here is part of me code - I have ListView with 2 elements.这是我的代码的一部分 - 我有 2 个元素的 ListView。 And 2nd is another 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 Added solution for changing scrolling physics of child with stream UPD添加了使用流更改子项滚动物理的解决方案

I build my Listview, like so:我构建了我的 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
        },
    ),

And then I build my 'TileWidget', like so:然后我构建我的“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(),
      ],
    );
  }
}

It's not very pretty.它不是很漂亮。 But it is simple and it works.但它很简单而且有效。

This might be a little late, but you can add NeverScrollableScrollPhysics() to the physics param of the ListView like this:这可能有点晚了,但您可以像这样将 NeverScrollableScrollPhysics() 添加到 ListView 的物理参数:

Widget buildLoadedWidget(CarouselCardsLoaded state) {
return ListView.builder(
  shrinkWrap: true,
  physics: NeverScrollableScrollPhysics(),
  itemBuilder: (context, i) {
    return GestureDetector(
      onTap: () async {

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM