build: 优化flutter触摸
This commit is contained in:
@@ -49,6 +49,14 @@ class _RemoteTouchViewState extends State<RemoteTouchView> {
|
|||||||
bool _isLongPressed = false;
|
bool _isLongPressed = false;
|
||||||
Timer? _longPressTimer;
|
Timer? _longPressTimer;
|
||||||
|
|
||||||
|
// 缓存 RenderBox 信息以优化坐标换算开销
|
||||||
|
RenderBox? _cachedRenderBox;
|
||||||
|
Size? _cachedSize;
|
||||||
|
|
||||||
|
// 采样率限制:控制 ACTION_MOVE 的发送频率(例如每 16ms 发送一次,约 60fps)
|
||||||
|
int _lastMoveTimestamp = 0;
|
||||||
|
static const int _sampleIntervalMs = 16;
|
||||||
|
|
||||||
/// 长按触发阈值,对应 Android GestureDetector 默认的 LONG_PRESS_TIMEOUT(400ms)。
|
/// 长按触发阈值,对应 Android GestureDetector 默认的 LONG_PRESS_TIMEOUT(400ms)。
|
||||||
static const _longPressTimeout = Duration(milliseconds: 400);
|
static const _longPressTimeout = Duration(milliseconds: 400);
|
||||||
|
|
||||||
@@ -76,14 +84,11 @@ class _RemoteTouchViewState extends State<RemoteTouchView> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Focus(
|
return Focus(
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
// 捕获物理按键(外接键盘 / 遥控器等)。
|
|
||||||
onKeyEvent: (node, event) {
|
onKeyEvent: (node, event) {
|
||||||
if (event is KeyDownEvent) {
|
if (event is KeyDownEvent) {
|
||||||
debugPrint('RemoteTouchView: KeyDown - ${event.logicalKey.debugName} (${event.logicalKey.keyId})');
|
|
||||||
widget.onKey(event.logicalKey.keyId, 0);
|
widget.onKey(event.logicalKey.keyId, 0);
|
||||||
return KeyEventResult.handled;
|
return KeyEventResult.handled;
|
||||||
} else if (event is KeyUpEvent) {
|
} else if (event is KeyUpEvent) {
|
||||||
debugPrint('RemoteTouchView: KeyUp - ${event.logicalKey.debugName} (${event.logicalKey.keyId})');
|
|
||||||
widget.onKey(event.logicalKey.keyId, 1);
|
widget.onKey(event.logicalKey.keyId, 1);
|
||||||
return KeyEventResult.handled;
|
return KeyEventResult.handled;
|
||||||
}
|
}
|
||||||
@@ -97,41 +102,42 @@ class _RemoteTouchViewState extends State<RemoteTouchView> {
|
|||||||
_startPosition = event.localPosition;
|
_startPosition = event.localPosition;
|
||||||
_currentPosition = event.localPosition;
|
_currentPosition = event.localPosition;
|
||||||
_startTime = DateTime.now();
|
_startTime = DateTime.now();
|
||||||
|
_lastMoveTimestamp = 0; // 重置采样计时
|
||||||
|
|
||||||
final size = context.size;
|
// 开始触摸时缓存 RenderBox 和 Size
|
||||||
if (size != null) {
|
_cachedRenderBox = context.findRenderObject() as RenderBox?;
|
||||||
final rx = _toRelativeX(event.localPosition, size);
|
_cachedSize = _cachedRenderBox?.size;
|
||||||
final ry = _toRelativeY(event.localPosition, size);
|
|
||||||
debugPrint('RemoteTouchView: PointerDown - relX: ${rx.toStringAsFixed(3)}, relY: ${ry.toStringAsFixed(3)}');
|
if (_cachedSize != null) {
|
||||||
widget.onMotionEvent(0, rx, ry);
|
final rx = _toRelativeX(event.localPosition, _cachedSize!);
|
||||||
|
final ry = _toRelativeY(event.localPosition, _cachedSize!);
|
||||||
|
widget.onMotionEvent(0, rx, ry); // ACTION_DOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
_longPressTimer = Timer(_longPressTimeout, () {
|
_longPressTimer = Timer(_longPressTimeout, () {
|
||||||
final size = context.size;
|
if (_currentPosition == null || _cachedSize == null) return;
|
||||||
if (_currentPosition == null || size == null) return;
|
|
||||||
_isLongPressed = true;
|
_isLongPressed = true;
|
||||||
final x = _toRelativeX(_currentPosition!, size);
|
final x = _toRelativeX(_currentPosition!, _cachedSize!);
|
||||||
final y = _toRelativeY(_currentPosition!, size);
|
final y = _toRelativeY(_currentPosition!, _cachedSize!);
|
||||||
debugPrint('RemoteTouchView: LongPress - relX: ${x.toStringAsFixed(3)}, relY: ${y.toStringAsFixed(3)}');
|
|
||||||
widget.onLongPress(x, y);
|
widget.onLongPress(x, y);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onPointerMove: (event) {
|
onPointerMove: (event) {
|
||||||
_currentPosition = event.localPosition;
|
_currentPosition = event.localPosition;
|
||||||
|
|
||||||
final size = context.size;
|
if (_cachedSize != null) {
|
||||||
if (size != null) {
|
final now = DateTime.now().millisecondsSinceEpoch;
|
||||||
final rx = _toRelativeX(event.localPosition, size);
|
// 采样率限制逻辑
|
||||||
final ry = _toRelativeY(event.localPosition, size);
|
if (now - _lastMoveTimestamp >= _sampleIntervalMs) {
|
||||||
// Move 事件较多,可以考虑控制日志频率,这里直接打印
|
_lastMoveTimestamp = now;
|
||||||
debugPrint('RemoteTouchView: PointerMove - relX: ${rx.toStringAsFixed(3)}, relY: ${ry.toStringAsFixed(3)}');
|
final rx = _toRelativeX(event.localPosition, _cachedSize!);
|
||||||
widget.onMotionEvent(2, rx, ry);
|
final ry = _toRelativeY(event.localPosition, _cachedSize!);
|
||||||
|
widget.onMotionEvent(2, rx, ry); // ACTION_MOVE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_longPressTimer != null && _startPosition != null) {
|
if (_longPressTimer != null && _startPosition != null) {
|
||||||
final dx = (event.localPosition.dx - _startPosition!.dx).abs();
|
if ((event.localPosition - _startPosition!).distance > _touchSlop) {
|
||||||
final dy = (event.localPosition.dy - _startPosition!.dy).abs();
|
|
||||||
if (dx > _touchSlop || dy > _touchSlop) {
|
|
||||||
_cancelLongPress();
|
_cancelLongPress();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,43 +145,32 @@ class _RemoteTouchViewState extends State<RemoteTouchView> {
|
|||||||
onPointerUp: (event) {
|
onPointerUp: (event) {
|
||||||
_cancelLongPress();
|
_cancelLongPress();
|
||||||
|
|
||||||
final size = context.size;
|
if (_cachedSize != null) {
|
||||||
if (size != null) {
|
final rx = _toRelativeX(event.localPosition, _cachedSize!);
|
||||||
final rx = _toRelativeX(event.localPosition, size);
|
final ry = _toRelativeY(event.localPosition, _cachedSize!);
|
||||||
final ry = _toRelativeY(event.localPosition, size);
|
widget.onMotionEvent(1, rx, ry); // ACTION_UP
|
||||||
debugPrint('RemoteTouchView: PointerUp - relX: ${rx.toStringAsFixed(3)}, relY: ${ry.toStringAsFixed(3)}');
|
|
||||||
widget.onMotionEvent(1, rx, ry);
|
if (!_isLongPressed && _startPosition != null && _startTime != null) {
|
||||||
|
final startX = _toRelativeX(_startPosition!, _cachedSize!);
|
||||||
|
final startY = _toRelativeY(_startPosition!, _cachedSize!);
|
||||||
|
final duration = DateTime.now().difference(_startTime!).inMilliseconds;
|
||||||
|
final dx = (rx - startX).abs();
|
||||||
|
final dy = (ry - startY).abs();
|
||||||
|
|
||||||
|
if (duration < 200 && dx < 0.02 && dy < 0.02) {
|
||||||
|
widget.onTouch(startX, startY);
|
||||||
|
} else {
|
||||||
|
widget.onSwipe(startX, startY, rx, ry, max(duration, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 长按已触发则不再派发单击 / 滑动事件(对应 Android 端 isLongPressed 逻辑)。
|
// 清理状态
|
||||||
if (_isLongPressed) {
|
|
||||||
_startPosition = null;
|
|
||||||
_currentPosition = null;
|
|
||||||
_startTime = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (_startPosition == null || size == null || _startTime == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final startX = _toRelativeX(_startPosition!, size);
|
|
||||||
final startY = _toRelativeY(_startPosition!, size);
|
|
||||||
final endX = _toRelativeX(event.localPosition, size);
|
|
||||||
final endY = _toRelativeY(event.localPosition, size);
|
|
||||||
final duration = DateTime.now().difference(_startTime!).inMilliseconds;
|
|
||||||
|
|
||||||
final dx = (endX - startX).abs();
|
|
||||||
final dy = (endY - startY).abs();
|
|
||||||
|
|
||||||
if (duration < 200 && dx < 0.02 && dy < 0.02) {
|
|
||||||
debugPrint('RemoteTouchView: Detected Touch - x: ${startX.toStringAsFixed(3)}, y: ${startY.toStringAsFixed(3)}');
|
|
||||||
widget.onTouch(startX, startY);
|
|
||||||
} else {
|
|
||||||
debugPrint('RemoteTouchView: Detected Swipe - from (${startX.toStringAsFixed(3)}, ${startY.toStringAsFixed(3)}) to (${endX.toStringAsFixed(3)}, ${endY.toStringAsFixed(3)}), duration: ${max(duration, 1)}ms');
|
|
||||||
widget.onSwipe(startX, startY, endX, endY, max(duration, 1));
|
|
||||||
}
|
|
||||||
_startPosition = null;
|
_startPosition = null;
|
||||||
_currentPosition = null;
|
_currentPosition = null;
|
||||||
_startTime = null;
|
_startTime = null;
|
||||||
|
_cachedRenderBox = null;
|
||||||
|
_cachedSize = null;
|
||||||
},
|
},
|
||||||
child: const ColoredBox(
|
child: const ColoredBox(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
@@ -185,3 +180,5 @@ class _RemoteTouchViewState extends State<RemoteTouchView> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user