Unverified Commit 9506d1e1 authored by Amir Hardon's avatar Amir Hardon Committed by GitHub

Add an EagerGestureRecognizer. (#21407)

This recognizer can be passed in AndroidView's gesureRecognizers when we
want all touch events in the view bounds to be immediately dispatched
to the Android view.
parent 7c477b93
......@@ -14,6 +14,7 @@ export 'src/gestures/converter.dart';
export 'src/gestures/debug.dart';
export 'src/gestures/drag.dart';
export 'src/gestures/drag_details.dart';
export 'src/gestures/eager.dart';
export 'src/gestures/events.dart';
export 'src/gestures/hit_test.dart';
export 'src/gestures/long_press.dart';
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'arena.dart';
import 'events.dart';
import 'recognizer.dart';
/// A gesture recognizer that eagerly claims victory in all gesture arenas.
///
/// This is typically passed in [AndroidView.gestureRecognizers] in order to immediately dispatch
/// all touch events inside the view bounds to the embedded Android view.
/// See [AndroidView.gestureRecognizers] for more details.
class EagerGestureRecognizer extends OneSequenceGestureRecognizer {
@override
void addPointer(PointerDownEvent event) {
// We call startTrackingPointer as this is where OneSequenceGestureRecognizer joins the arena.
startTrackingPointer(event.pointer);
resolve(GestureDisposition.accepted);
stopTrackingPointer(event.pointer);
}
@override
String get debugDescription => 'eager';
@override
void didStopTrackingLastPointer(int pointer) {}
@override
void handleEvent(PointerEvent event) {}
}
......@@ -96,6 +96,37 @@ class AndroidView extends StatefulWidget {
/// that was put down on the widget. If any of the recognizers on this list wins the
/// gesture arena, the entire pointer event sequence starting from the pointer down event
/// will be dispatched to the Android view.
///
/// For example, with the following setup vertical drags will not be dispatched to the Android
/// view as the vertical drag gesture is claimed by the parent [GestureDetector].
/// ```dart
/// GestureDetector(
/// onVerticalDragStart: (DragStartDetails d) {},
/// child: AndroidView(
/// viewType: 'webview',
/// gestureRecognizers: <OneSequenceGestureRecognizer>[],
/// ),
/// )
/// ```
/// To get the [AndroidView] to claim the vertical drag gestures we can pass a vertical drag
/// gesture recognizer in [gestureRecognizers] e.g:
/// ```dart
/// GestureDetector(
/// onVerticalDragStart: (DragStartDetails d) {},
/// child: SizedBox(
/// width: 200.0,
/// height: 100.0,
/// child: AndroidView(
/// viewType: 'webview',
/// gestureRecognizers: <OneSequenceGestureRecognizer>[ new VerticalDragGestureRecognizer() ],
/// ),
/// ),
/// )
/// ```
///
/// An [AndroidView] can be configured to consume all pointers that were put down in its bounds
/// by passing an [EagerGestureRecognizer] in [gestureRecognizers]. [EagerGestureRecognizer] is a
/// special gesture recognizer that immediately claims the gesture after a pointer down event.
// We use OneSequenceGestureRecognizers as they support gesture arena teams.
// TODO(amirh): get a list of GestureRecognizers here.
// https://github.com/flutter/flutter/issues/20953
......
......@@ -669,4 +669,40 @@ void main() {
]),
);
});
testWidgets('Android view with eager gesture recognizer', (WidgetTester tester) async {
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
final FakePlatformViewsController viewsController = new FakePlatformViewsController(TargetPlatform.android);
viewsController.registerViewType('webview');
await tester.pumpWidget(
new Align(
alignment: Alignment.topLeft,
child: GestureDetector(
onVerticalDragStart: (DragStartDetails d) {},
child: SizedBox(
width: 200.0,
height: 100.0,
child: AndroidView(
viewType: 'webview',
gestureRecognizers: <OneSequenceGestureRecognizer>[ new EagerGestureRecognizer() ],
layoutDirection: TextDirection.ltr,
),
),
),
),
);
await tester.startGesture(const Offset(50.0, 50.0));
// Normally (without the eager gesture recognizer) after just the pointer down event
// no gesture arena member will claim the arena (so no motion events will be dispatched to
// the Android view). Here we assert that with the eager recognizer in the gesture team the
// pointer down event is immediately dispatched.
expect(
viewsController.motionEvents[currentViewId + 1],
orderedEquals(<FakeMotionEvent> [
const FakeMotionEvent(AndroidViewController.kActionDown, <int> [0], <Offset> [Offset(50.0, 50.0)]),
]),
);
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment