垂直滚动pageView中颤动的垂直滚动listView

时间:2019-10-17 23:26:00

标签: flutter flutter-layout

在此方面寻求帮助,乍看起来似乎很简单,但是却无法解决...

基本上,我正在尝试制作一个具有垂直可滚动listView的垂直可滚动listView的页面。例如,列表在页面2上,用户在页面1上,然后向下滚动到页面2。现在,他向下滚动直到列表的末尾,我希望他能够滚动到比页面更多的位置3。

关于如何实施此建议?

2 个答案:

答案 0 :(得分:1)

对我有用的是,我们需要附加ListView的滚动控制器以侦听滚动位置。然后页面控制器将移至下一页或上一页。

PageController pageController;
ScrollController scrollController;

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

  pageController = PageController();
  scrollController = ScrollController();

  scrollController.addListener(() {
    // listView reaches the bottom
    if (scrollController.offset >= scrollController.position.maxScrollExtent - 100 &&
      !scrollController.position.outOfRange) {
      pageController.nextPage(duration: const Duration(seconds: 1), curve: ElasticOutCurve());
    }

    // listView reaches the top
    if (scrollController.offset <= scrollController.position.minScrollExtent &&
        !scrollController.position.outOfRange) {
      pageController.previousPage(duration: const Duration(seconds:1), curve: ElasticOutCurve());
    }
  });
}

别忘了连接控制器

PageView(
  controller: pageController,
  ...


ListView(
  controller: scrollController,
  ...

答案 1 :(得分:1)

此GitHub issue有一个方便的解决方案,我认为您需要的每个页面之间都有“悬停”行为。这是线程中提供的示例代码:

void main() => runApp(App());

class App extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: Example()
      )
    );
  }

}

class Example extends StatefulWidget {

  @override
  _ExampleState createState() => _ExampleState();

}

class _ExampleState extends State<Example> {

  PageController _pageController;
  ScrollController _listScrollController;
  ScrollController _activeScrollController;
  Drag _drag;

  @override
  void initState() {
    super.initState();
    _pageController = PageController();
    _listScrollController = ScrollController();
  }

  @override
  void dispose() {
    _pageController.dispose();
    _listScrollController.dispose();
    super.dispose();
  }

  void _handleDragStart(DragStartDetails details) {
    if (_listScrollController.hasClients && _listScrollController.position.context.storageContext != null) {
      final RenderBox renderBox = _listScrollController.position.context.storageContext.findRenderObject();
      if (renderBox.paintBounds.shift(renderBox.localToGlobal(Offset.zero)).contains(details.globalPosition)) {
        _activeScrollController = _listScrollController;
        _drag = _activeScrollController.position.drag(details, _disposeDrag);
        return;
      }
    }
    _activeScrollController = _pageController;
    _drag = _pageController.position.drag(details, _disposeDrag);
  }

  void _handleDragUpdate(DragUpdateDetails details) {
    if (_activeScrollController == _listScrollController && details.primaryDelta < 0 && _activeScrollController.position.pixels == _activeScrollController.position.maxScrollExtent) {
      _activeScrollController = _pageController;
      _drag?.cancel();
      _drag = _pageController.position.drag(
        DragStartDetails(
          globalPosition: details.globalPosition,
          localPosition: details.localPosition
        ),
        _disposeDrag
      );
    }
    _drag?.update(details);
  }

  void _handleDragEnd(DragEndDetails details) {
    _drag?.end(details);
  }

  void _handleDragCancel() {
    _drag?.cancel();
  }

  void _disposeDrag() {
    _drag = null;
  }

  @override
  Widget build(BuildContext context) {
    return RawGestureDetector(
      gestures: <Type, GestureRecognizerFactory>{
          VerticalDragGestureRecognizer: GestureRecognizerFactoryWithHandlers<VerticalDragGestureRecognizer>(
          () => VerticalDragGestureRecognizer(),
          (VerticalDragGestureRecognizer instance) {
            instance
              ..onStart = _handleDragStart
              ..onUpdate = _handleDragUpdate
              ..onEnd = _handleDragEnd
              ..onCancel = _handleDragCancel;
          }
          )
      },
      behavior: HitTestBehavior.opaque,
      child: PageView(
        controller: _pageController,
        scrollDirection: Axis.vertical,
        physics: const NeverScrollableScrollPhysics(),
        children: [
          ListView(
            controller: _listScrollController,
            physics: const NeverScrollableScrollPhysics(),
            children: List.generate(
              25,
              (int index) {
                return ListTile(
                  title: Text('Item $index')
                );
              }
            )
          ),
          Center(
            child: Text('Page 2')
          )
        ],
      )
    );
  }

}