首页 > 其他分享 >通过 Listener 解决 Slider 滑动冲突

通过 Listener 解决 Slider 滑动冲突

时间:2023-08-15 13:07:06浏览次数:44  
标签:SingleChildScrollView value height Listener Slider 滑动

问题背景 

Flutter 中,我们经常使用 ScrollView + Slider 这样的场景。

但是在这样的场景下,存在用户体验并不好的问题:

列表滑动的过程中 Slider 不能响应

举例:


1\. 滑动未完成,Slider 不能响应

SingleChildScrollView 在我们手指抬起的过程中,还是会有一定的惯性, 列表不会立刻停止。它这样做是为了用户体验,让用户感觉到丝滑。

当遇到 Slider 会发生什么情况?

不能滑动

可以滑动

以下是未处理的效果:

以下是优化后的效果:

通过 Listener 解决 Slider 滑动冲突_解决方案

通过 Listener 解决 Slider 滑动冲突_ci_02

以上是开启了 FlutterDisable Slow Animations 功能展示的效果

慢动画展示的效果

根据视频观察到:

当手指抬起时,列表会根据惯性滑动一段距离,如果此时点击列表,列表会停止滑动

意味着,如果用户想在这个时候想滑动 Slider 的话,需要等 SingleChildScrollView 完全停止的情况下,才可以滑动 Slider

2\. 滑动溢出,Slider 不能响应

SingleChildScrollView 中设置了 physicsBouncingScrollPhysics()

这样设置后 ScrollView 就会有滑动溢出的效果,对于用户来说能获得较好的用户体验

但是不巧的是 Slider 在这种情况下不能响应滑动事件

不能滑动

可以滑动

以下是未处理的效果:

以下是优化后的效果:

3\. 解决方案

一句话总结:ListeneronPointerMove 中计算 value 值。

具体方案:

  • 通过 Listener 监听原始指针事件,拿到 PointerEvent 对象。
  • 再通过 GlobalKey 拿到 SliderSingleChildScrollView 中的位置。
  • 通过他们可以在 onPointerMove 中计算 Slidervalue 的值应该滑动的位置。
class SliderPage extends StatefulWidget {
  @override
  _SliderPageState createState() => _SliderPageState();
}

Rect rect = Rect.zero;

class _SliderPageState extends State<SliderPage> {
  String? text;
  double value = 0;
  GlobalKey key = GlobalKey();
  ScrollController controller = ScrollController();

  Widget _buildBody() {
    return SizedBox(
      height: MediaQuery.of(context).size.height,
      child: Listener(
        onPointerMove: (p) {
          final box = key.currentContext!.findRenderObject()! as RenderBox;
          final offset = box.localToGlobal(Offset.zero);
          final size = box.size;
          rect = Rect.fromPoints(offset, offset.translate(size.width, size.height));
          setState(() {});

          if (rect.contains(p.position)) {
            value = ((p.position.dx) / (rect.width - 2 * 24 )).clamp(0, 1);
            setState(() {});
          }
        },
        child: Column(
          children: [
            SizedBox(
              height: 555,
              child: SingleChildScrollView(
                controller: controller,
                physics: BouncingScrollPhysics(),
                dragStartBehavior: DragStartBehavior.down,
                child: Column(
                  children: [
                    Container(
                      height: 444,
                      color: Colors.blue,
                    ),
                    Listener(
                      onPointerDown: (p) {},
                      onPointerMove: (p) {
                        // print('Slider ${p}');
                      },
                      child: Slider(
                        key: key,
                        value: value,
                        autofocus: true,
                        onChanged: (v) {
                          value = v;
                          setState(() {});
                        },
                      ),
                    ),
                    Container(
                      height: 333,
                      color: Colors.blue,
                    ),
                  ],
                ),
              ),
            ),
            Expanded(child: Container(color: Colors.blue))
          ],
        ),
      ),
    );
  }
4\. 总结:
  1. Slider 只有当 SingleChildScrollView 完全停止的情况下才可以其他事件。

原因: 当指针按下时,Flutter 会对应用程序执行命中测试(Hit Test) ,以确定指针与屏幕接触的位置存在哪些组件(widget), 指针按下事件(以及该指针的后续事件)然后被分发到由命中测试发现的最内部的组件

  1. Listener 中计算 value 值,可能是不准确。因为拿到 Sinder 的长度还需要拿到 SinderPadding,才能保证计算的准确性。
  2. 这篇文章提供一个解决滑动冲突的思路,如果有其他思路欢迎沟通交流。

想要了解更多Anrloid相关知识可以点击下方课堂链接                  https://edu.51cto.com/course/32703.html Android课


标签:SingleChildScrollView,value,height,Listener,Slider,滑动
From: https://blog.51cto.com/u_16163480/7086794

相关文章

  • Oracle启动监听报错:The listener supports no services或出现 unknown状态解决
    1、查看$ORACLE_HOME/network/admin/listener.ora文件中的host是否正确,能不能ping通2、查看$ORACLE_HOME/network/admin/tnsnames.ora文件中的host是否与listener.ora中的一致3、查看/etc/hosts文件中的127.0.0.1是不是localhost,listener.ora中host跟这里的是否一样4、登录数......
  • 滑动分页列表数据重复或丢失问题
    滑动分页列表数据重复或丢失问题链接https://juejin.cn/post/7073519311213559822darifo2022-03-1101:251999 背景在某CMS系统中,由于后台管理高频的操作新增、删除、调整了数据顺序,导致APP用户在滑动分页获取数据时返回重复或丢失数据。主要出现场景:APP用户上滑......
  • tkinter Canvas加滑动条为什么变灰没用
    因为还要设置Canvas的滑动范围:通过canvas的对象方法scrollregion设置如,设置为全部,则为canvas1.configure(scrollregion=c.bbox("all")) 示例代码(ChatGPT写的):fromtkinterimport*defon_canvas_configure(event):canvas.configure(scrollregion=canvas.bbox("all"......
  • web三大组件之一Listener
    什么是Listener监听器?1、Listener监听器它是JavaWeb的三大组件之一。JavaWeb的三大组件分别是:Servlet程序、Filter过滤器、Listener监听器。2、Listener它是JavaEE的规范,就是接口3、监听器的作用是,监听某种事物的变化。然后通过回调函数,反馈给客户(程序)去做一些相应的......
  • 老杜 JavaWeb 讲解(二十) ——Listener监听器
    (十八)Listener监听器引子:静态代码块packagecom.zwm.javaweb.servlet;/***@author猪无名*@date2023/8/81347*discription:*/publicclasstest2{//静态代码块在类加载时执行,并且只执行一次。//这个语法很简单,但什么时候用?很疑惑//假如,你希......
  • 代码随想录算法训练营第十三天| 239. 滑动窗口最大值 347.前 K 个高频元素 总结
    239.滑动窗口最大值 (一刷至少需要理解思路)    卡哥建议:之前讲的都是栈的应用,这次该是队列的应用了。本题算比较有难度的,需要自己去构造单调队列,建议先看视频来理解。    题目链接/文章讲解/视频讲解:https://programmercarl.com/0239.%E6%BB%91%E5%8A%A8%E7%AA%......
  • 【快应用】list组件如何区分滑动的方向?
    ​ 【关键词】list组件、滑动方向、scroll 【问题背景】有cp反馈list这个组件在使用的时候,不知道如何区分它是上滑还是下滑。 【问题分析】list组件除了通用事件之外,还提供了scroll、scrollbottom、scrolltop、scrollend、scrolltouchup事件,对应的描述如下图所示:​要......
  • 小程序滑动删除
    参考项目:国际择校小程序,组件:movableView,提交版本:效果:使用了别人写的组件,cell动态高度需要计算,这块稍微麻烦一点计算高度代码:properties:{ item:{ type:Object, value:{}, observer:function(val){ console.log('---??',val,'type?',this.proper......
  • 在线直播系统源码,移动端列表左右滑动效果
    在线直播系统源码,移动端列表左右滑动效果<view class="evaluationItem">                <scroll-view class="uni-swiper-tab" scroll-x :style="'height:'+scrollH+'px'">                    <view class="scrollx_i......
  • vue实现一个鼠标滑动预览视频封面组件(精灵图版本)
    说在前面......