未验证 提交 36ca5740 编写于 作者: C Chris Yang 提交者: GitHub

[platform_views] Fix duplicated touch event pass down to flutter view from platform view. (#8026)

Fix for flutter/flutter#27700 and flutter/flutter#24207

There are 2 fixes included in this PR.

The intercepting views sometime pass up the touches events to flutter view, even after the forward gesture recognizer pass the event to the flutter view. We only want the event to be passed to the flutter view once. So we let the intercepting view 'consumes' the event in this PR to fix the problem.

When a touch sequence has multiple touch points participated(e.g. Pinch gesture), the touchesBegan and touchesEnded can be triggered multiple times if the touches do not happen simultaneously. One example would be: when performing a pinch gesture with 2 fingers, I put down one finger, keep the finger on the screen, then put down another finger, perform pinch, lift up both finger at the same time. In this sequence, touchesBegan is called twice with each touch in one of the calls and touchesEnded is called once and has 2 touches in the callback. To handle this issue, we added a count to count the touches in one touch sequence. We only set the state to fail when the count reaches 0(That is all the touches has began in the current sequence is ended).
上级 3d53e202
......@@ -353,6 +353,21 @@ void FlutterPlatformViewsController::EnsureGLOverlayInitialized(
_delayingRecognizer.get().state = UIGestureRecognizerStateEnded;
}
// We want the intercepting view to consume the touches and not pass the touches up to the parent
// view. Make the touch event method not call super will not pass the touches up to the parent view.
// Hence we overide the touch event methods and do nothing.
- (void)touchesBegan:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event {
}
- (void)touchesMoved:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event {
}
- (void)touchesCancelled:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event {
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
}
@end
@implementation DelayingGestureRecognizer {
......@@ -395,6 +410,8 @@ void FlutterPlatformViewsController::EnsureGLOverlayInitialized(
// So this is safe as when FlutterView is deallocated the reference to ForwardingGestureRecognizer
// will go away.
UIView* _flutterView;
// Counting the pointers that has started in one touch sequence.
NSInteger _currentTouchPointersCount;
}
- (instancetype)initWithTarget:(id)target flutterView:(UIView*)flutterView {
......@@ -402,12 +419,15 @@ void FlutterPlatformViewsController::EnsureGLOverlayInitialized(
if (self) {
self.delegate = self;
_flutterView = flutterView;
_currentTouchPointersCount = 0;
}
return self;
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
[_flutterView touchesBegan:touches withEvent:event];
_currentTouchPointersCount += touches.count;
[_flutterView touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
......@@ -416,11 +436,19 @@ void FlutterPlatformViewsController::EnsureGLOverlayInitialized(
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
[_flutterView touchesEnded:touches withEvent:event];
self.state = UIGestureRecognizerStateFailed;
_currentTouchPointersCount -= touches.count;
// Touches in one touch sequence are sent to the touchesEnded method separately if different
// fingers stop touching the screen at different time. So one touchesEnded method triggering does
// not necessarially mean the touch sequence has ended. We Only set the state to
// UIGestureRecognizerStateFailed when all the touches in the current touch sequence is ended.
if (_currentTouchPointersCount == 0) {
self.state = UIGestureRecognizerStateFailed;
}
}
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event {
[_flutterView touchesCancelled:touches withEvent:event];
_currentTouchPointersCount = 0;
self.state = UIGestureRecognizerStateFailed;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册