diff --git a/webrtc_controller_flutter/lib/widgets/remote_touch_view.dart b/webrtc_controller_flutter/lib/widgets/remote_touch_view.dart index 8bb0125..ab6bbe7 100644 --- a/webrtc_controller_flutter/lib/widgets/remote_touch_view.dart +++ b/webrtc_controller_flutter/lib/widgets/remote_touch_view.dart @@ -49,6 +49,14 @@ class _RemoteTouchViewState extends State { bool _isLongPressed = false; 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)。 static const _longPressTimeout = Duration(milliseconds: 400); @@ -76,14 +84,11 @@ class _RemoteTouchViewState extends State { Widget build(BuildContext context) { return Focus( autofocus: true, - // 捕获物理按键(外接键盘 / 遥控器等)。 onKeyEvent: (node, event) { if (event is KeyDownEvent) { - debugPrint('RemoteTouchView: KeyDown - ${event.logicalKey.debugName} (${event.logicalKey.keyId})'); widget.onKey(event.logicalKey.keyId, 0); return KeyEventResult.handled; } else if (event is KeyUpEvent) { - debugPrint('RemoteTouchView: KeyUp - ${event.logicalKey.debugName} (${event.logicalKey.keyId})'); widget.onKey(event.logicalKey.keyId, 1); return KeyEventResult.handled; } @@ -97,41 +102,42 @@ class _RemoteTouchViewState extends State { _startPosition = event.localPosition; _currentPosition = event.localPosition; _startTime = DateTime.now(); + _lastMoveTimestamp = 0; // 重置采样计时 - final size = context.size; - if (size != null) { - final rx = _toRelativeX(event.localPosition, size); - final ry = _toRelativeY(event.localPosition, size); - debugPrint('RemoteTouchView: PointerDown - relX: ${rx.toStringAsFixed(3)}, relY: ${ry.toStringAsFixed(3)}'); - widget.onMotionEvent(0, rx, ry); + // 开始触摸时缓存 RenderBox 和 Size + _cachedRenderBox = context.findRenderObject() as RenderBox?; + _cachedSize = _cachedRenderBox?.size; + + if (_cachedSize != null) { + final rx = _toRelativeX(event.localPosition, _cachedSize!); + final ry = _toRelativeY(event.localPosition, _cachedSize!); + widget.onMotionEvent(0, rx, ry); // ACTION_DOWN } _longPressTimer = Timer(_longPressTimeout, () { - final size = context.size; - if (_currentPosition == null || size == null) return; + if (_currentPosition == null || _cachedSize == null) return; _isLongPressed = true; - final x = _toRelativeX(_currentPosition!, size); - final y = _toRelativeY(_currentPosition!, size); - debugPrint('RemoteTouchView: LongPress - relX: ${x.toStringAsFixed(3)}, relY: ${y.toStringAsFixed(3)}'); + final x = _toRelativeX(_currentPosition!, _cachedSize!); + final y = _toRelativeY(_currentPosition!, _cachedSize!); widget.onLongPress(x, y); }); }, onPointerMove: (event) { _currentPosition = event.localPosition; - - final size = context.size; - if (size != null) { - final rx = _toRelativeX(event.localPosition, size); - final ry = _toRelativeY(event.localPosition, size); - // Move 事件较多,可以考虑控制日志频率,这里直接打印 - debugPrint('RemoteTouchView: PointerMove - relX: ${rx.toStringAsFixed(3)}, relY: ${ry.toStringAsFixed(3)}'); - widget.onMotionEvent(2, rx, ry); + + if (_cachedSize != null) { + final now = DateTime.now().millisecondsSinceEpoch; + // 采样率限制逻辑 + if (now - _lastMoveTimestamp >= _sampleIntervalMs) { + _lastMoveTimestamp = now; + final rx = _toRelativeX(event.localPosition, _cachedSize!); + final ry = _toRelativeY(event.localPosition, _cachedSize!); + widget.onMotionEvent(2, rx, ry); // ACTION_MOVE + } } if (_longPressTimer != null && _startPosition != null) { - final dx = (event.localPosition.dx - _startPosition!.dx).abs(); - final dy = (event.localPosition.dy - _startPosition!.dy).abs(); - if (dx > _touchSlop || dy > _touchSlop) { + if ((event.localPosition - _startPosition!).distance > _touchSlop) { _cancelLongPress(); } } @@ -139,43 +145,32 @@ class _RemoteTouchViewState extends State { onPointerUp: (event) { _cancelLongPress(); - final size = context.size; - if (size != null) { - final rx = _toRelativeX(event.localPosition, size); - final ry = _toRelativeY(event.localPosition, size); - debugPrint('RemoteTouchView: PointerUp - relX: ${rx.toStringAsFixed(3)}, relY: ${ry.toStringAsFixed(3)}'); - widget.onMotionEvent(1, rx, ry); + if (_cachedSize != null) { + final rx = _toRelativeX(event.localPosition, _cachedSize!); + final ry = _toRelativeY(event.localPosition, _cachedSize!); + widget.onMotionEvent(1, rx, ry); // ACTION_UP + + 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; _currentPosition = null; _startTime = null; + _cachedRenderBox = null; + _cachedSize = null; }, child: const ColoredBox( color: Colors.transparent, @@ -185,3 +180,5 @@ class _RemoteTouchViewState extends State { ); } } + +