diff --git a/examples/material_gallery/android/AndroidManifest.xml b/examples/material_gallery/android/AndroidManifest.xml index 049316483b..2fbd96d14e 100644 --- a/examples/material_gallery/android/AndroidManifest.xml +++ b/examples/material_gallery/android/AndroidManifest.xml @@ -6,6 +6,7 @@ + diff --git a/packages/flutter/lib/src/gestures/drag.dart b/packages/flutter/lib/src/gestures/drag.dart index 8f0ab80963..5cdee0f6d2 100644 --- a/packages/flutter/lib/src/gestures/drag.dart +++ b/packages/flutter/lib/src/gestures/drag.dart @@ -143,6 +143,8 @@ class VerticalDragGestureRecognizer extends _DragGestureRecognizer { double get _initialPendingDragDelta => 0.0; double _getDragDelta(PointerEvent event) => event.delta.dy; bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop; + + String toStringShort() => 'vertical drag'; } class HorizontalDragGestureRecognizer extends _DragGestureRecognizer { @@ -163,6 +165,8 @@ class HorizontalDragGestureRecognizer extends _DragGestureRecognizer { double get _initialPendingDragDelta => 0.0; double _getDragDelta(PointerEvent event) => event.delta.dx; bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop; + + String toStringShort() => 'horizontal drag'; } class PanGestureRecognizer extends _DragGestureRecognizer { @@ -185,4 +189,6 @@ class PanGestureRecognizer extends _DragGestureRecognizer { bool get _hasSufficientPendingDragDeltaToAccept { return _pendingDragDelta.distance > kPanSlop; } + + String toStringShort() => 'pan'; } diff --git a/packages/flutter/lib/src/gestures/long_press.dart b/packages/flutter/lib/src/gestures/long_press.dart index 3abb49a602..0e3a02743f 100644 --- a/packages/flutter/lib/src/gestures/long_press.dart +++ b/packages/flutter/lib/src/gestures/long_press.dart @@ -34,4 +34,6 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer { if (event is PointerUpEvent) resolve(GestureDisposition.rejected); } + + String toStringShort() => 'long press'; } diff --git a/packages/flutter/lib/src/gestures/multidrag.dart b/packages/flutter/lib/src/gestures/multidrag.dart index 1b9ab89b84..064888e7ac 100644 --- a/packages/flutter/lib/src/gestures/multidrag.dart +++ b/packages/flutter/lib/src/gestures/multidrag.dart @@ -250,6 +250,8 @@ class ImmediateMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_Im _ImmediatePointerState createNewPointerState(PointerDownEvent event) { return new _ImmediatePointerState(event.position); } + + String toStringShort() => 'multidrag'; } @@ -277,6 +279,8 @@ class HorizontalMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_H _HorizontalPointerState createNewPointerState(PointerDownEvent event) { return new _HorizontalPointerState(event.position); } + + String toStringShort() => 'horizontal multidrag'; } @@ -304,6 +308,8 @@ class VerticalMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_Ver _VerticalPointerState createNewPointerState(PointerDownEvent event) { return new _VerticalPointerState(event.position); } + + String toStringShort() => 'vertical multidrag'; } @@ -373,4 +379,6 @@ class DelayedMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_Dela _DelayedPointerState createNewPointerState(PointerDownEvent event) { return new _DelayedPointerState(event.position, _delay); } + + String toStringShort() => 'long multidrag'; } diff --git a/packages/flutter/lib/src/gestures/multitap.dart b/packages/flutter/lib/src/gestures/multitap.dart index 9f40fefe42..263a92803c 100644 --- a/packages/flutter/lib/src/gestures/multitap.dart +++ b/packages/flutter/lib/src/gestures/multitap.dart @@ -212,6 +212,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { } } + String toStringShort() => 'double tap'; } @@ -385,4 +386,5 @@ class MultiTapGestureRecognizer extends GestureRecognizer { _gestureArena = null; } + String toStringShort() => 'multitap'; } diff --git a/packages/flutter/lib/src/gestures/recognizer.dart b/packages/flutter/lib/src/gestures/recognizer.dart index 6438da30c0..3595096962 100644 --- a/packages/flutter/lib/src/gestures/recognizer.dart +++ b/packages/flutter/lib/src/gestures/recognizer.dart @@ -42,6 +42,9 @@ abstract class GestureRecognizer extends GestureArenaMember { /// GestureDetector widget calls this method). void dispose() { } + /// Returns a very short pretty description of the gesture that the + /// recognizer looks for, like 'tap' or 'horizontal drag'. + String toStringShort() => toString(); } /// Base class for gesture recognizers that can only recognize one diff --git a/packages/flutter/lib/src/gestures/scale.dart b/packages/flutter/lib/src/gestures/scale.dart index e8d46347c6..77d9f018ff 100644 --- a/packages/flutter/lib/src/gestures/scale.dart +++ b/packages/flutter/lib/src/gestures/scale.dart @@ -135,4 +135,6 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { } _state = ScaleState.ready; } + + String toStringShort() => 'scale'; } diff --git a/packages/flutter/lib/src/gestures/tap.dart b/packages/flutter/lib/src/gestures/tap.dart index 76bc0059c0..d3d028961e 100644 --- a/packages/flutter/lib/src/gestures/tap.dart +++ b/packages/flutter/lib/src/gestures/tap.dart @@ -102,4 +102,6 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer { _wonArena = false; _finalPosition = null; } + + String toStringShort() => 'tap'; } diff --git a/packages/flutter/lib/src/widgets/gesture_detector.dart b/packages/flutter/lib/src/widgets/gesture_detector.dart index bc7c923d02..8f38bef70c 100644 --- a/packages/flutter/lib/src/widgets/gesture_detector.dart +++ b/packages/flutter/lib/src/widgets/gesture_detector.dart @@ -28,6 +28,8 @@ export 'package:flutter/gestures.dart' show GestureScaleEndCallback, Velocity; +typedef GestureRecognizer GestureRecognizerFactory(GestureRecognizer recognizer, PointerRouter router, GestureArena arena); + /// A widget that detects gestures. /// /// Attempts to recognize gestures that correspond to its non-null callbacks. @@ -37,8 +39,8 @@ export 'package:flutter/gestures.dart' show /// [excludeFromSemantics] to true. /// /// See http://flutter.io/gestures/ for additional information. -class GestureDetector extends StatefulComponent { - const GestureDetector({ +class GestureDetector extends StatelessComponent { + GestureDetector({ Key key, this.child, this.onTapDown, @@ -61,7 +63,23 @@ class GestureDetector extends StatefulComponent { this.onScaleEnd, this.behavior, this.excludeFromSemantics: false - }) : super(key: key); + }) : super(key: key) { + assert(excludeFromSemantics != null); + assert(() { + bool haveVerticalDrag = onVerticalDragStart != null || onVerticalDragUpdate != null || onVerticalDragEnd != null; + bool haveHorizontalDrag = onHorizontalDragStart != null || onHorizontalDragUpdate != null || onHorizontalDragEnd != null; + bool havePan = onPanStart != null || onPanUpdate != null || onPanEnd != null; + bool haveScale = onScaleStart != null || onScaleUpdate != null || onScaleEnd != null; + if (havePan || haveScale) { + if (havePan && haveScale) + throw new WidgetError('Having both a pan gesture recognizer and a scale gesture recognizer is redundant; scale is a superset of pan. Just use the scale gesture recognizer.'); + String recognizer = havePan ? 'pan' : 'scale'; + if (haveVerticalDrag && haveHorizontalDrag) + throw new WidgetError('Simultaneously having a vertical drag gesture recognizer, a horizontal drag gesture recognizer, and a $recognizer gesture recognizer will result in the $recognizer gesture recognizer being ignored, since the other two will catch all drags.'); + } + return true; + }); + } final Widget child; @@ -130,151 +148,192 @@ class GestureDetector extends StatefulComponent { /// duplication of information. final bool excludeFromSemantics; - _GestureDetectorState createState() => new _GestureDetectorState(); + Widget build(BuildContext context) { + Map gestures = {}; + + if (onTapDown != null || onTapUp != null || onTap != null || onTapCancel != null) { + gestures[TapGestureRecognizer] = (TapGestureRecognizer recognizer, PointerRouter router, GestureArena arena) { + return (recognizer ??= new TapGestureRecognizer(router: router, gestureArena: arena)) + ..onTapDown = onTapDown + ..onTapUp = onTapUp + ..onTap = onTap + ..onTapCancel = onTapCancel; + }; + } + + if (onDoubleTap != null) { + gestures[DoubleTapGestureRecognizer] = (DoubleTapGestureRecognizer recognizer, PointerRouter router, GestureArena arena) { + return (recognizer ??= new DoubleTapGestureRecognizer(router: router, gestureArena: arena)) + ..onDoubleTap = onDoubleTap; + }; + } + + if (onLongPress != null) { + gestures[LongPressGestureRecognizer] = (LongPressGestureRecognizer recognizer, PointerRouter router, GestureArena arena) { + return (recognizer ??= new LongPressGestureRecognizer(router: router, gestureArena: arena)) + ..onLongPress = onLongPress; + }; + } + + if (onVerticalDragStart != null || onVerticalDragUpdate != null || onVerticalDragEnd != null) { + gestures[VerticalDragGestureRecognizer] = (VerticalDragGestureRecognizer recognizer, PointerRouter router, GestureArena arena) { + return (recognizer ??= new VerticalDragGestureRecognizer(router: router, gestureArena: arena)) + ..onStart = onVerticalDragStart + ..onUpdate = onVerticalDragUpdate + ..onEnd = onVerticalDragEnd; + }; + } + + if (onHorizontalDragStart != null || onHorizontalDragUpdate != null || onHorizontalDragEnd != null) { + gestures[HorizontalDragGestureRecognizer] = (HorizontalDragGestureRecognizer recognizer, PointerRouter router, GestureArena arena) { + return (recognizer ??= new HorizontalDragGestureRecognizer(router: router, gestureArena: arena)) + ..onStart = onHorizontalDragStart + ..onUpdate = onHorizontalDragUpdate + ..onEnd = onHorizontalDragEnd; + }; + } + + if (onPanStart != null || onPanUpdate != null || onPanEnd != null) { + gestures[PanGestureRecognizer] = (PanGestureRecognizer recognizer, PointerRouter router, GestureArena arena) { + return (recognizer ??= new PanGestureRecognizer(router: router, gestureArena: arena)) + ..onStart = onPanStart + ..onUpdate = onPanUpdate + ..onEnd = onPanEnd; + }; + } + + if (onScaleStart != null || onScaleUpdate != null || onScaleEnd != null) { + gestures[ScaleGestureRecognizer] = (ScaleGestureRecognizer recognizer, PointerRouter router, GestureArena arena) { + return (recognizer ??= new ScaleGestureRecognizer(router: router, gestureArena: arena)) + ..onStart = onScaleStart + ..onUpdate = onScaleUpdate + ..onEnd = onScaleEnd; + }; + } + + return new RawGestureDetector( + gestures: gestures, + behavior: behavior, + excludeFromSemantics: excludeFromSemantics, + child: child + ); + } } -class _GestureDetectorState extends State { - PointerRouter get _router => Gesturer.instance.pointerRouter; +/// A widget that detects gestures described by the given gesture +/// factories. +/// +/// For common gestures, use a [GestureRecognizer]. +/// RawGestureDetector is useful primarily when developing your +/// own gesture recognizers. +class RawGestureDetector extends StatefulComponent { + RawGestureDetector({ + Key key, + this.child, + this.gestures: const {}, + this.behavior, + this.excludeFromSemantics: false + }) : super(key: key) { + assert(gestures != null); + assert(excludeFromSemantics != null); + } - TapGestureRecognizer _tap; - DoubleTapGestureRecognizer _doubleTap; - LongPressGestureRecognizer _longPress; - VerticalDragGestureRecognizer _verticalDrag; - HorizontalDragGestureRecognizer _horizontalDrag; - PanGestureRecognizer _pan; - ScaleGestureRecognizer _scale; + final Widget child; + + final Map gestures; + + /// How this gesture detector should behave during hit testing. + final HitTestBehavior behavior; + + /// Whether to exclude these gestures from the semantics tree. For + /// example, the long-press gesture for showing a tooltip is + /// excluded because the tooltip itself is included in the semantics + /// tree directly and so having a gesture to show it would result in + /// duplication of information. + final bool excludeFromSemantics; + + RawGestureDetectorState createState() => new RawGestureDetectorState(); +} + +class RawGestureDetectorState extends State { + + Map _recognizers = const {}; void initState() { super.initState(); - _syncAll(); + _syncAll(config.gestures); } - void didUpdateConfig(GestureDetector oldConfig) { - _syncAll(); + void didUpdateConfig(RawGestureDetector oldConfig) { + _syncAll(config.gestures); + } + + /// This method can be called after the build phase, during the + /// layout of the nearest descendant RenderObjectWidget of the + /// gesture detector, to update the list of active gesture + /// recognizers. + /// + /// The typical use case is [Scrollable]s, which put their viewport + /// in their gesture detector, and then need to know the dimensions + /// of the viewport and the viewport's child to determine whether + /// the gesture detector should be enabled. + void replaceGestureRecognizers(Map gestures) { + assert(() { + RenderObject renderObject = context.findRenderObject(); + assert(renderObject is RenderPointerListener); + RenderPointerListener listener = renderObject; + RenderBox descendant = listener.child; + if (!config.excludeFromSemantics) { + assert(descendant is RenderSemanticsGestureHandler); + RenderSemanticsGestureHandler semanticsGestureHandler = descendant; + descendant = semanticsGestureHandler.child; + } + assert(descendant != null); + if (!descendant.debugDoingThisLayout) { + throw new WidgetError( + 'replaceGestureRecognizers() can only be called during the layout phase of the GestureDetector\'s nearest descendant RenderObjectWidget.\n' + 'In this particular case, that is:\n' + ' $descendant' + ); + } + return true; + }); + _syncAll(gestures); + if (!config.excludeFromSemantics) { + RenderPointerListener listener = context.findRenderObject(); + RenderSemanticsGestureHandler semanticsGestureHandler = listener.child; + context.visitChildElements((RenderObjectElement element) => element.widget.updateRenderObject(semanticsGestureHandler, null)); + } } void dispose() { - _tap = _ensureDisposed(_tap); - _doubleTap = _ensureDisposed(_doubleTap); - _longPress = _ensureDisposed(_longPress); - _verticalDrag = _ensureDisposed(_verticalDrag); - _horizontalDrag = _ensureDisposed(_horizontalDrag); - _pan = _ensureDisposed(_pan); - _scale = _ensureDisposed(_scale); + for (GestureRecognizer recognizer in _recognizers.values) + recognizer.dispose(); + _recognizers = null; super.dispose(); } - void _syncAll() { - _syncTap(); - _syncDoubleTap(); - _syncLongPress(); - _syncVerticalDrag(); - _syncHorizontalDrag(); - _syncPan(); - _syncScale(); - } - - void _syncTap() { - if (config.onTapDown == null && config.onTapUp == null && config.onTap == null && config.onTapCancel == null) { - _tap = _ensureDisposed(_tap); - } else { - _tap ??= new TapGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena); - _tap - ..onTapDown = config.onTapDown - ..onTapUp = config.onTapUp - ..onTap = config.onTap - ..onTapCancel = config.onTapCancel; + void _syncAll(Map gestures) { + final PointerRouter pointerRouter = Gesturer.instance.pointerRouter; + final GestureArena gestureArena = Gesturer.instance.gestureArena; + assert(_recognizers != null); + Map oldRecognizers = _recognizers; + _recognizers = {}; + for (Type type in gestures.keys) { + assert(!_recognizers.containsKey(type)); + _recognizers[type] = gestures[type](oldRecognizers[type], pointerRouter, gestureArena); + assert(_recognizers[type].runtimeType == type); } - } - - void _syncDoubleTap() { - if (config.onDoubleTap == null) { - _doubleTap = _ensureDisposed(_doubleTap); - } else { - _doubleTap ??= new DoubleTapGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena); - _doubleTap.onDoubleTap = config.onDoubleTap; + for (Type type in oldRecognizers.keys) { + if (!_recognizers.containsKey(type)) + oldRecognizers[type].dispose(); } } - void _syncLongPress() { - if (config.onLongPress == null) { - _longPress = _ensureDisposed(_longPress); - } else { - _longPress ??= new LongPressGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena); - _longPress.onLongPress = config.onLongPress; - } - } - - void _syncVerticalDrag() { - if (config.onVerticalDragStart == null && config.onVerticalDragUpdate == null && config.onVerticalDragEnd == null) { - _verticalDrag = _ensureDisposed(_verticalDrag); - } else { - _verticalDrag ??= new VerticalDragGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena); - _verticalDrag - ..onStart = config.onVerticalDragStart - ..onUpdate = config.onVerticalDragUpdate - ..onEnd = config.onVerticalDragEnd; - } - } - - void _syncHorizontalDrag() { - if (config.onHorizontalDragStart == null && config.onHorizontalDragUpdate == null && config.onHorizontalDragEnd == null) { - _horizontalDrag = _ensureDisposed(_horizontalDrag); - } else { - _horizontalDrag ??= new HorizontalDragGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena); - _horizontalDrag - ..onStart = config.onHorizontalDragStart - ..onUpdate = config.onHorizontalDragUpdate - ..onEnd = config.onHorizontalDragEnd; - } - } - - void _syncPan() { - if (config.onPanStart == null && config.onPanUpdate == null && config.onPanEnd == null) { - _pan = _ensureDisposed(_pan); - } else { - assert(_scale == null); // Scale is a superset of pan; just use scale - _pan ??= new PanGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena); - _pan - ..onStart = config.onPanStart - ..onUpdate = config.onPanUpdate - ..onEnd = config.onPanEnd; - } - } - - void _syncScale() { - if (config.onScaleStart == null && config.onScaleUpdate == null && config.onScaleEnd == null) { - _scale = _ensureDisposed(_scale); - } else { - assert(_pan == null); // Scale is a superset of pan; just use scale - _scale ??= new ScaleGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena); - _scale - ..onStart = config.onScaleStart - ..onUpdate = config.onScaleUpdate - ..onEnd = config.onScaleEnd; - } - } - - GestureRecognizer _ensureDisposed(GestureRecognizer recognizer) { - recognizer?.dispose(); - return null; - } - void _handlePointerDown(PointerDownEvent event) { - if (_tap != null) - _tap.addPointer(event); - if (_doubleTap != null) - _doubleTap.addPointer(event); - if (_longPress != null) - _longPress.addPointer(event); - if (_verticalDrag != null) - _verticalDrag.addPointer(event); - if (_horizontalDrag != null) - _horizontalDrag.addPointer(event); - if (_pan != null) - _pan.addPointer(event); - if (_scale != null) - _scale.addPointer(event); + assert(_recognizers != null); + for (GestureRecognizer recognizer in _recognizers.values) + recognizer.addPointer(event); } HitTestBehavior get _defaultBehavior { @@ -287,47 +346,21 @@ class _GestureDetectorState extends State { behavior: config.behavior ?? _defaultBehavior, child: config.child ); - if (!config.excludeFromSemantics) { - result = new _GestureSemantics( - onTapDown: config.onTapDown, - onTapUp: config.onTapUp, - onTap: config.onTap, - onLongPress: config.onLongPress, - onVerticalDragStart: config.onVerticalDragStart, - onVerticalDragUpdate: config.onVerticalDragUpdate, - onVerticalDragEnd: config.onVerticalDragEnd, - onHorizontalDragStart: config.onHorizontalDragStart, - onHorizontalDragUpdate: config.onHorizontalDragUpdate, - onHorizontalDragEnd: config.onHorizontalDragEnd, - onPanStart: config.onPanStart, - onPanUpdate: config.onPanUpdate, - onPanEnd: config.onPanEnd, - child: result - ); - } + if (!config.excludeFromSemantics) + result = new _GestureSemantics(owner: this, child: result); return result; } void debugFillDescription(List description) { super.debugFillDescription(description); - List gestures = []; - if (_tap != null) - gestures.add('tap'); - if (_doubleTap != null) - gestures.add('double tap'); - if (_longPress != null) - gestures.add('long press'); - if (_verticalDrag != null) - gestures.add('vertical drag'); - if (_horizontalDrag != null) - gestures.add('horizontal drag'); - if (_pan != null) - gestures.add('pan'); - if (_scale != null) - gestures.add('scale'); - if (gestures.isEmpty) - gestures.add(''); - description.add('gestures: ${gestures.join(", ")}'); + if (_recognizers == null) { + description.add('DISPOSED'); + } else { + List gestures = _recognizers.values.map/**/((GestureRecognizer recognizer) => recognizer.toStringShort()); + if (gestures.isEmpty) + gestures.add(''); + description.add('gestures: ${gestures.join(", ")}'); + } switch (config.behavior) { case HitTestBehavior.translucent: description.add('behavior: translucent'); @@ -345,118 +378,99 @@ class _GestureDetectorState extends State { class _GestureSemantics extends OneChildRenderObjectWidget { _GestureSemantics({ Key key, - this.onTapDown, - this.onTapUp, - this.onTap, - this.onLongPress, - this.onVerticalDragStart, - this.onVerticalDragUpdate, - this.onVerticalDragEnd, - this.onHorizontalDragStart, - this.onHorizontalDragUpdate, - this.onHorizontalDragEnd, - this.onPanStart, - this.onPanUpdate, - this.onPanEnd, - Widget child + Widget child, + this.owner }) : super(key: key, child: child); - final GestureTapDownCallback onTapDown; - final GestureTapUpCallback onTapUp; - final GestureTapCallback onTap; - final GestureLongPressCallback onLongPress; - final GestureDragStartCallback onVerticalDragStart; - final GestureDragUpdateCallback onVerticalDragUpdate; - final GestureDragEndCallback onVerticalDragEnd; - final GestureDragStartCallback onHorizontalDragStart; - final GestureDragUpdateCallback onHorizontalDragUpdate; - final GestureDragEndCallback onHorizontalDragEnd; - final GesturePanStartCallback onPanStart; - final GesturePanUpdateCallback onPanUpdate; - final GesturePanEndCallback onPanEnd; - - bool get _watchingTaps { - return onTapDown != null - || onTapUp != null - || onTap != null; - } - - bool get _watchingHorizontalDrags { - return onHorizontalDragStart != null - || onHorizontalDragUpdate != null - || onHorizontalDragEnd != null; - } - - bool get _watchingVerticalDrags { - return onVerticalDragStart != null - || onVerticalDragUpdate != null - || onVerticalDragEnd != null; - } - - bool get _watchingPans { - return onPanStart != null - || onPanUpdate != null - || onPanEnd != null; - } + final RawGestureDetectorState owner; void _handleTap() { - if (onTapDown != null) - onTapDown(Point.origin); - if (onTapUp != null) - onTapUp(Point.origin); - if (onTap != null) - onTap(); + TapGestureRecognizer recognizer = owner._recognizers[TapGestureRecognizer]; + assert(recognizer != null); + if (recognizer.onTapDown != null) + recognizer.onTapDown(Point.origin); + if (recognizer.onTapUp != null) + recognizer.onTapUp(Point.origin); + if (recognizer.onTap != null) + recognizer.onTap(); + } + + void _handleLongPress() { + LongPressGestureRecognizer recognizer = owner._recognizers[LongPressGestureRecognizer]; + assert(recognizer != null); + if (recognizer.onLongPress != null) + recognizer.onLongPress(); } void _handleHorizontalDragUpdate(double delta) { - if (_watchingHorizontalDrags) { - if (onHorizontalDragStart != null) - onHorizontalDragStart(Point.origin); - if (onHorizontalDragUpdate != null) - onHorizontalDragUpdate(delta); - if (onHorizontalDragEnd != null) - onHorizontalDragEnd(Velocity.zero); - } else { - assert(_watchingPans); - if (onPanStart != null) - onPanStart(Point.origin); - if (onPanUpdate != null) - onPanUpdate(new Offset(delta, 0.0)); - if (onPanEnd != null) - onPanEnd(Velocity.zero); + { + HorizontalDragGestureRecognizer recognizer = owner._recognizers[HorizontalDragGestureRecognizer]; + if (recognizer != null) { + if (recognizer.onStart != null) + recognizer.onStart(Point.origin); + if (recognizer.onUpdate != null) + recognizer.onUpdate(delta); + if (recognizer.onEnd != null) + recognizer.onEnd(Velocity.zero); + return; + } } + { + PanGestureRecognizer recognizer = owner._recognizers[PanGestureRecognizer]; + if (recognizer != null) { + if (recognizer.onStart != null) + recognizer.onStart(Point.origin); + if (recognizer.onUpdate != null) + recognizer.onUpdate(new Offset(delta, 0.0)); + if (recognizer.onEnd != null) + recognizer.onEnd(Velocity.zero); + return; + } + } + assert(false); } void _handleVerticalDragUpdate(double delta) { - if (_watchingVerticalDrags) { - if (onVerticalDragStart != null) - onVerticalDragStart(Point.origin); - if (onVerticalDragUpdate != null) - onVerticalDragUpdate(delta); - if (onVerticalDragEnd != null) - onVerticalDragEnd(Velocity.zero); - } else { - assert(_watchingPans); - if (onPanStart != null) - onPanStart(Point.origin); - if (onPanUpdate != null) - onPanUpdate(new Offset(0.0, delta)); - if (onPanEnd != null) - onPanEnd(Velocity.zero); + { + VerticalDragGestureRecognizer recognizer = owner._recognizers[VerticalDragGestureRecognizer]; + if (recognizer != null) { + if (recognizer.onStart != null) + recognizer.onStart(Point.origin); + if (recognizer.onUpdate != null) + recognizer.onUpdate(delta); + if (recognizer.onEnd != null) + recognizer.onEnd(Velocity.zero); + return; + } } + { + PanGestureRecognizer recognizer = owner._recognizers[PanGestureRecognizer]; + if (recognizer != null) { + if (recognizer.onStart != null) + recognizer.onStart(Point.origin); + if (recognizer.onUpdate != null) + recognizer.onUpdate(new Offset(0.0, delta)); + if (recognizer.onEnd != null) + recognizer.onEnd(Velocity.zero); + return; + } + } + assert(false); } - RenderSemanticsGestureHandler createRenderObject() => new RenderSemanticsGestureHandler( - onTap: _watchingTaps ? _handleTap : null, - onLongPress: onLongPress, - onHorizontalDragUpdate: _watchingHorizontalDrags || _watchingPans ? _handleHorizontalDragUpdate : null, - onVerticalDragUpdate: _watchingVerticalDrags || _watchingPans ? _handleVerticalDragUpdate : null - ); + RenderSemanticsGestureHandler createRenderObject() { + RenderSemanticsGestureHandler result = new RenderSemanticsGestureHandler(); + updateRenderObject(result, null); + return result; + } void updateRenderObject(RenderSemanticsGestureHandler renderObject, _GestureSemantics oldWidget) { - renderObject.onTap = _watchingTaps ? _handleTap : null; - renderObject.onLongPress = onLongPress; - renderObject.onHorizontalDragUpdate = _watchingHorizontalDrags || _watchingPans ? _handleHorizontalDragUpdate : null; - renderObject.onVerticalDragUpdate = _watchingVerticalDrags || _watchingPans ? _handleVerticalDragUpdate : null; + Map recognizers = owner._recognizers; + renderObject.onTap = recognizers.containsKey(TapGestureRecognizer) ? _handleTap : null; + renderObject.onLongPress = recognizers.containsKey(LongPressGestureRecognizer) ? _handleLongPress : null; + renderObject.onHorizontalDragUpdate = recognizers.containsKey(VerticalDragGestureRecognizer) || + recognizers.containsKey(PanGestureRecognizer) ? _handleHorizontalDragUpdate : null; + renderObject.onVerticalDragUpdate = recognizers.containsKey(VerticalDragGestureRecognizer) || + recognizers.containsKey(PanGestureRecognizer) ? _handleVerticalDragUpdate : null; } }