Flutter “颤振腹板”;“平滑滚动”;在页面视图中显示事件

Flutter “颤振腹板”;“平滑滚动”;在页面视图中显示事件,flutter,flutter-web,mousewheel,smooth-scrolling,flutter-pageview,Flutter,Flutter Web,Mousewheel,Smooth Scrolling,Flutter Pageview,使用下面的代码 导入“包装:颤振/材料.省道”; void main()=>runApp(MyApp()); 类MyApp扩展了无状态小部件{ constmyapp({Key}):超级(Key:Key); @凌驾 小部件构建(构建上下文)=>MaterialApp( 主页:const MyHomePage(), ); } 类MyHomePage扩展了无状态小部件{ constmyhomepage({Key}):超级(Key:Key); @凌驾 小部件构建(BuildContext上下文)=>De

使用下面的代码

导入“包装:颤振/材料.省道”;
void main()=>runApp(MyApp());
类MyApp扩展了无状态小部件{
constmyapp({Key}):超级(Key:Key);
@凌驾
小部件构建(构建上下文)=>MaterialApp(
主页:const MyHomePage(),
);
}
类MyHomePage扩展了无状态小部件{
constmyhomepage({Key}):超级(Key:Key);
@凌驾
小部件构建(BuildContext上下文)=>DefaultTabController(
长度:2,
孩子:脚手架(
appBar:appBar(
标题:康斯特中心(
child:Text('使用鼠标滚轮滚动'),
底部:选项卡栏(
制表符:常数[
居中(子项:文本(“滚动视图”),
居中(子项:文本('PageView'))
],
),
),
正文:选项卡视图(
儿童:[
SingleChildScrollView(
子:列(
儿童:[
对于(int i=0;i<10;i++)
容器(
高度:MediaQuery.of(context).size.height,
孩子:康斯特中心(
儿童:标志(尺寸:80),
),
),
],
),
),
页面浏览(
滚动方向:轴垂直,
儿童:[
对于(int i=0;i<10;++i)
康斯特中心(
儿童:标志(尺寸:80),
),
],
),
],
),
),
);
}
你可以看到,在上面或从上面运行

使用鼠标滚轮滚动
页面视图
提供了一种平庸的体验(最多)

这是一个已知的问题,但我正试图找到一个解决办法

实现
页面视图的平滑滚动
或至少防止“口吃”

有人能帮我解决问题或给我指出正确的方向吗

我不确定问题出在
PageScrollPhysics

我有一种直觉,问题可能出在


由于使用多点触控滚动进行滑动可以完美地工作

问题在于用户设置,最终用户如何使用鼠标设置滚动。我有一个Logitech鼠标,可以通过Logitech选项打开或关闭平滑滚动功能。当我启用平滑滚动时,它可以完美地工作并按需要滚动,但如果禁用平滑滚动,它也会在项目中被禁用。行为由最终用户设置

但是,如果需要强制滚动到平滑滚动,则只能通过设置相关动画来完成。目前还没有直接的办法


问题源于一连串事件:

  • 用户将鼠标滚轮旋转一个凹槽
  • Scrollable
    接收
    PointerSignal
    jumpTo
    方法
  • \u PagePosition
    的方法(源于带有SingleContext的
    ScrollPosition
    )更新滚动位置并调用
    Goballitic
    方法
  • PageScrollPhysics
    模拟将位置恢复为初始值,因为一个槽口偏移产生的偏移太小,无法翻页
  • 从步骤(1)重复另一个切口和过程
  • 解决此问题的一种方法是在调用
    goBallistic
    方法之前执行延迟。这可以在类中完成,但是类是私有的,我们必须修补颤振SDK:

    ///packages/flatter/lib/src/widgets/page\u view.dart
    // ...
    类_PagePosition使用SingleContext扩展ScrollPosition实现PageMetrics{
    //...
    //添加此代码以解决此问题(主要是从ScrollPositionWithSingleContext借用的):
    定时器;
    @凌驾
    无效跳转到(双值){
    戈德尔();
    如果(像素!=值){
    最终双像素=像素;
    像素(值);
    didStartScroll();
    didUpdateScrollPositionBy(像素-旧像素);
    didendcoll();
    }
    if(timer!=null)timer.cancel();
    计时器=计时器(持续时间(毫秒:200),(){
    戈巴利斯特(0.0);
    定时器=空;
    });
    }
    // ...
    }
    
    另一种方法是用animateTo替换jumpTo。这可以在不修补Flatter SDK的情况下完成,但看起来更复杂,因为我们需要禁用默认的
    PointerSignalEvent
    listener:

    导入'dart:async';
    导入“package:flatter/signatures.dart”;
    进口“包装:颤振/材料.省道”;
    导入“package:flatter/rendering.dart”;
    类PageViewLab扩展StatefulWidget{
    @凌驾
    _PageViewLabState createState()=>\u PageViewLabState();
    }
    类_PageViewLabState扩展状态{
    最终接收器=StreamController();
    final pager=PageController();
    @凌驾
    void initState(){
    super.initState();
    节流阀(下沉流)。侦听((偏移){
    寻呼机动画(
    抵消,
    持续时间:持续时间(毫秒:200),
    曲线:曲线,
    );
    });
    }
    @凌驾
    无效处置(){
    sink.close();
    dispose();
    super.dispose();
    }
    @凌驾
    小部件构建(构建上下文){
    返回脚手架(
    appBar:appBar(
    标题:文本(“带页面视图的鼠标滚轮”),
    ),
    主体:容器(
    约束:BoxConstraints.expand(),
    孩子:听众(
    onPointerSignal:_handlePointerSignal,
    子项:_IgnorePointerSignal(
    子项:PageView.builder(
    控制器:寻呼机,
    滚动方向:轴垂直,
    itemCount:Color.primaries.length,
    itemBuilder:(上下文,索引){
    返回填充(
    填充:常数边集全部(8.0),
    子:容器(颜色:Colors.primaries[inde
    
    ...
    dependencies:
        ...
        smooth_scroll_web: ^0.0.4
    ...