PageView:禁用默认滚动并将其替换为 Tap 事件

Posted

技术标签:

【中文标题】PageView:禁用默认滚动并将其替换为 Tap 事件【英文标题】:PageView: Disable the default scrolling and replace it with Tap event 【发布时间】:2018-06-11 03:38:59 【问题描述】:

如果我有PageView,如何禁用默认滚动行为(滑动)并通过点击按钮将下一个项目滚动到视图中?

【问题讨论】:

【参考方案1】:

要禁用滑动,您可以设置:

PageView(physics: NeverScrollableScrollPhysics())

【讨论】:

这不会禁用使用PageController 滚动的功能吗? 如果我想禁用滑动并在按下按钮时滑动到下一个怎么办? 只是为了回答@SakchhamSharma 的问题:这只会禁用滑动,您仍然可以通过控制器以编程方式为其他页面设置动画,例如_controller.nextPage() 嗨@JannieTheunissen,我的意思是专门滚动。你可以换页,是的;但是动画由于底层NeverScrollableScrollPhysics而受到限制。【参考方案2】:

所以我尝试了以下方法,如果有人有更好的解决方案,请与我们分享。

制作一个按钮转到PageView 中的下一项:

PageController 添加到您的PageView,并在用户按下按钮时使用animateTojumpTo 方法转到所需的项目。我已经使当前视图的整个宽度都是偏移量,因此到下一个项目的转换成功发生。

onPressed: () 
        c.animateTo(MediaQuery
            .of(context)
            .size
            .width, duration: new Duration(seconds: 1),
            curve: Curves.easeIn);
      

 

禁用默认滑动行为:

我所做的只是将我的 PageView 包裹在 IgnorePointer 中以忽略任何用户交互,我真的不喜欢这个解决方案,在这个例子中它可能工作得很好,但是在其他情况下我可能想要用户与当前显示页面中的单个小部件进行交互。

这是我的示例代码:

class FirstPage extends StatefulWidget 
  @override
  _FirstPageState createState() => new _FirstPageState();


class _FirstPageState extends State<FirstPage> 
  ScrollController c;

  @override
  void initState() 
    super.initState();
    c = new PageController();
  

  @override
  Widget build(BuildContext context) 
    return new Scaffold(
      floatingActionButton: new Row(
        mainAxisAlignment: MainAxisAlignment.end,
        crossAxisAlignment: CrossAxisAlignment.end,

        children: <Widget>[
          new FloatingActionButton(
              child: new Icon(Icons.navigate_before), onPressed: () 
            //c.animateTo(MediaQuery.of(context).size.width, duration: new Duration(seconds: 1), curve: Curves.easeIn);
            c.jumpTo(0.0);
          ),
          new Container(width: 15.0,),
          new FloatingActionButton(
              child: new Icon(Icons.navigate_next), onPressed: () 
            c.animateTo(MediaQuery
                .of(context)
                .size
                .width, duration: new Duration(seconds: 1),
                curve: Curves.easeIn);
          ),
        ],),
      appBar: new AppBar(title: new Text("First Page")),
      body: new IgnorePointer(child: new PageView(
        controller: c,
        children: <Widget>[
          new Column (
              children: <Widget>[new Container (child: new Text("First Item"))
              ]),
          new Container (child: new Text("Second Item")),
        ],
      ),),
    );
  

欢迎对此解决方案提出任何建议或修改。

【讨论】:

是否可以检测页面视图中的向前和向后滑动事件?使用监听器? @ShyjuMadathil 和 PageViewController 您可以添加将在事件更改时触发的侦听器。但是,PageView.builder() 为您提供了 onPageChanged 属性,当页面向前或向后更改时触发,我相信这就是您要寻找的。​​span> 我刚才试过了。我能够以这种方式在多个页面上运行MediaQuery.of (context) .size.width * (pageIndex + 1)。几乎我有 70 页来自更多。 这种方法无法在页面视图中使用文本字段【参考方案3】:

停止滚动的最佳方法是更改​​页面视图的物理参数

如果 PageView 在开始或结束时停止滚动过去的边缘

physics: ClampingScrollPhysics()

要完全停止滚动,请使用

physics: NeverScrollableScrollPhysics()

【讨论】:

【参考方案4】:

可能对某些人有所帮助的附加说明。

如果您在其中一个停止对手势做出反应的页面中有动态 GoogleMap,则使用 PageView(physics:new NeverScrollableScrollPhysics()) 非常有用。似乎 PageView 优先并覆盖了地图。

添加 NeverScrollablePhysics() 允许地图再次对手势做出反应。

谢谢

【讨论】:

【参考方案5】:

要禁用手势滑动,请将以下属性添加到您的 PageView:

PageView(physics:new NeverScrollableScrollPhysics())

要导航到 PageView 中的下一页/小部件,请将以下代码添加到按钮的 onPressed 属性:

_pageController.nextPage(
     duration: Duration(milliseconds: 1000),
     curve: Curves.easeIn
);

【讨论】:

以上是关于PageView:禁用默认滚动并将其替换为 Tap 事件的主要内容,如果未能解决你的问题,请参考以下文章

禁用滚动视图中的反弹禁用 pageView 控制器中的水平滚动

如何在 Flutter 中创建垂直滚动的 PageView?

在可缩放的滚动视图中禁用图像视图缩放

如何在 Webview 中禁用滚动?

如何覆盖 OnBeforeUnload 对话框并将其替换为我自己的?

扑。 PageView 内的嵌套滚动