Flutter中如何让组件沿用户滑动的正确方向持续移动?
解决Flutter滑动结束后容器沿正确方向持续移动的问题
你的问题核心是没有利用滑动结束时的真实速度方向,而是硬编码了dx++和dy++,导致只能朝固定方向移动。要实现沿用户滑动的正确方向持续移动,需要借助DragEndDetails提供的速度向量来计算后续的偏移量,同时可以加入减速逻辑让运动更符合物理直觉。
修改后的完整代码
import 'dart:async'; import 'package:flutter/material.dart'; class Test extends StatefulWidget { const Test({Key? key}) : super(key: key); @override State<Test> createState() => _TestState(); } class _TestState extends State<Test> { Offset myOffset = const Offset(0, 0); Timer? _moveTimer; Offset _currentVelocity = Offset.zero; // 减速因子,值越小减速越快,范围0-1 final double _deceleration = 0.95; // 最小速度阈值,低于此值停止运动 final double _minVelocity = 2; @override Widget build(BuildContext context) { return Scaffold( body: Center( child: GestureDetector( onPanUpdate: (details) { // 滑动过程中更新容器位置 setState(() { myOffset += details.delta; }); // 如果之前的运动还在进行,停止它 _moveTimer?.cancel(); }, onPanEnd: (details) { // 获取滑动结束时的速度(每秒移动的像素) _currentVelocity = details.velocity.pixelsPerSecond; // 启动持续移动的定时器 _moveTimer?.cancel(); _moveTimer = Timer.periodic(const Duration(milliseconds: 16), (_) { setState(() { // 计算本次定时器回调的位移增量(16ms约为60帧的间隔) final delta = _currentVelocity * 0.016; myOffset += delta; // 应用减速,让速度逐渐减小 _currentVelocity *= _deceleration; }); // 当速度小于阈值时,停止定时器 if (_currentVelocity.distance < _minVelocity) { _moveTimer?.cancel(); _moveTimer = null; } }); }, child: Transform.translate( offset: myOffset, child: Container( color: Colors.red, width: 100, height: 100, ), ), ), ), ); } @override void dispose() { // 页面销毁时取消定时器,避免内存泄漏 _moveTimer?.cancel(); super.dispose(); } }
关键修改点说明
- 利用滑动速度向量:
details.velocity.pixelsPerSecond直接给出了滑动结束时的速度方向和大小,这是实现正确方向移动的核心。
- 加入减速逻辑:
- 通过
_deceleration减速因子让速度逐渐衰减,模拟真实世界的滑动惯性,同时设置_minVelocity阈值,当速度足够小时停止运动。
- 通过
- 优化定时器间隔:
- 使用16ms的间隔(接近屏幕60帧的刷新频率),让动画更流畅。
- 滑动过程中停止惯性运动:
- 在
onPanUpdate中取消之前的定时器,避免用户再次滑动时出现冲突的运动状态。
- 在
- 内存泄漏防护:
- 在
dispose方法中取消定时器,确保页面销毁时资源被正确释放。
- 在
内容的提问来源于stack exchange,提问作者Mohammed Hamdan
相关产品推荐
相关产品推荐

