NotificationListener如何监听DraggableScrollableNotification滚动结束
问题解答
完全可以实现,不需要在每一帧都触发方法调用。DraggableScrollableNotification自带状态字段可以直接识别交互阶段、判断滚动/拖拽操作是否完全结束。
核心判断逻辑
DraggableScrollableNotification提供了两个关键信息用来判定操作状态:
dragging字段:布尔类型,值为true时代表用户正按住面板拖拽,值为false时代表用户已经抬手,直接拖拽操作终止extent字段:当前面板占父容器的尺寸比例,如果你开启了snap吸附效果,用户抬手后面板会自动执行吸附动画,这时候dragging已经为false但动画还在运行,需要额外判断extent是否已经稳定到配置的吸附点、或者最小/最大尺寸边界,才能认定整个滚动+吸附流程完全结束。
注意:浮点数比较需要加微小容差,不要直接用
==判断,避免浮点计算精度问题导致判断失效。
完整实现代码
NotificationListener<DraggableScrollableNotification>( onNotification: (notification) { // 拖拽过程中直接返回,不执行业务逻辑 if (notification.dragging) return false; // 汇总所有面板可能停止的位置 final validStopPositions = <double>[ _minChildSize, _maxChildSize, ..._snapSizes, ]; // 校验当前位置是否已经到达停止点,容差设为0.001规避浮点精度问题 final currentExtent = notification.extent; final isOperationEnd = validStopPositions.any( (pos) => (currentExtent - pos).abs() < 0.001, ); // 只有交互完全结束时才执行业务方法 if (isOperationEnd) { func.call(); } return true; }, child: DraggableScrollableSheet( initialChildSize: _initialChildSize, snap: true, snapSizes: _snapSizes, minChildSize: _minChildSize, maxChildSize: _maxChildSize, controller: _sheetController, builder: (context, controller) { return _customScrollView(); }, ), )
额外提示
- 如果没有开启
snap吸附效果,不需要做位置校验,只要判断notification.dragging == false即可认定操作结束 - 该方案只会在交互完全终止时触发一次业务方法,拖拽过程、吸附动画过程都不会执行额外逻辑,完全避免每帧调用带来的不必要性能开销。
内容的提问来源于stack exchange,提问作者qwerty
相关产品推荐
相关产品推荐

