【问题标题】:How to handle scrollview gestures inside a Flutter PageView?如何处理 Flutter PageView 中的滚动视图手势?
【发布时间】:2020-04-29 21:01:18
【问题描述】:
  1. 我的问题总结

目标

我的目标是展示一个带有长页面的轮播。 所以我使用带有滚动视图的 PageView。 PageView 水平滚动。 滚动视图(子视图)垂直滚动。

预期结果

水平滑动和垂直滚动。

实际结果

如果我水平滑动到下一页,我无法立即垂直滚动它。 我需要等待 1 秒钟。 似乎用户必须等待动画完成才能与新的当前页面进行交互。

到目前为止我做了什么:

  • 我尝试使用手势识别器来传递拖动事件,但没有成功。
  • 我尝试了不同的小部件来替换 PageView 但效果相同。
  • 我尝试了 AutomaticKeepAliveClientMixin 与 wantKeepAlive = true
  • 我试过 PageView.physics = AlwaysScrollableScrollPhysics()

这是重现问题所需的最少代码

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: carousel(),
    );
  }

  Widget carousel() {
    return PageView(
      children: <Widget>[
        page(Colors.pinkAccent),
        page(Colors.blueAccent),
        page(Colors.orangeAccent)
      ],
    );
  }

  Widget page(Color color) {
    return Container(
        decoration: BoxDecoration(
          color: color,
        ),
        child: SingleChildScrollView(
          child: Column(
              children: pageContent()),
        ));
  }

  List<Widget> pageContent() {
    return <Widget>[
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
      Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
    ];
  }
}

【问题讨论】:

  • 你找到解决办法了吗?

标签: flutter scrollview gesture flutter-pageview


【解决方案1】:

经过一番挖掘,我相信问题出在 PageView 的 DragStartBehavior 上。为了平滑,PageView 的默认行为最终感觉迟缓,页面快照几乎感觉就像喝了太多酒。

这意味着当您想要垂直滚动时,PageView 仍然在变化中模糊不清。

当您调用 PageView 时调整 DragStartBehavior,它会感觉更加反应灵敏 - 感觉更加活泼,我相信这可以解决您的问题。

Widget carousel() {
    return PageView(
      children: <Widget>[
        dragStartBehavior: DragStartBehavior.down,
        page(Colors.pinkAccent),
        page(Colors.blueAccent),
        page(Colors.orangeAccent)
      ],
    );
  }

p.s 谢谢 Yunnosch 的谴责和笑声:) 也可以随意编辑,因为我还不能准确评论!

【讨论】:

  • 即使你引用了你违反的规则,它仍然适用于你。 meta.stackexchange.com/questions/214173/… 因此,如果您真的认为您发布的内容不是答案,那么不要。请采取tour 更好地了解。但幸运的是,我看到实际尝试过的答案比你认为的评论更糟糕......在这里也被认为不合适....
  • 在下一次发布准评论未回答之前,请更好地研究How to Answer,这样就不会那么幸运了。否则欢迎使用 StackOverflow 并玩得开心。
  • 感谢您的回答。但是,这无助于使我的旋转木马顺利进行。 (PS:您的示例中有一个错字,“dragStartBehavior”应该在 PageView 构造函数中)。
【解决方案2】:

我成功找到了一个解决方案,让我的 PageView 在水平和垂直方向上都非常流畅。

我禁用 PageView.pageSnapping 以使轮播非常流畅。 但是我失去了磁效应,所以我使用 NotificationListener 来捕获 ScrollEndNotification 事件。 当滚动结束时,我计算出对用户最可见的页面并调用 PageController.animateToPage() 来完成这项工作。

代码如下所示:

Widget getCarousel() {

  return NotificationListener<ScrollNotification>(
  onNotification: (scrollNotification) {

    if (scrollNotification is ScrollEndNotification) {
      print("ScrollEndNotification");

      Future.delayed(const Duration(milliseconds: 0), () {
        int newPage = pageController.page.round();
        print("end at $newPage");
        pageController.animateToPage(newPage, duration: Duration(milliseconds: 400), curve: Curves.fastOutSlowIn);
      });
    }
    return true;
  },
  child: PageView.builder(
    scrollDirection: Axis.horizontal,
    pageSnapping: false,
    controller: pageController,
    itemBuilder: (BuildContext context, int index) {
      return myPages[index];
    },
  )
);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-08
    • 1970-01-01
    相关资源
    最近更新 更多