Add hitTesting to allow changing click behavior in embeds

The code change allows to override the default behaviour of clicking on
images and thus solves #90. 

Now the only thing left to do is to use a `RawGestureDetector` in the 
`EmbedBuilder` to deactivate the "old" behaviour (by entering the 
GestureArena and win). The `embedBuilder` could look like this:
```dart
Widget embedBuilder(BuildContext context, Embed node, bool readOnly) {
  return FutureBuilder<File>(
    future: File('image_path.png'),
    builder: (context, snapshot) {
      final gestures = {
        ReadDependentGestureRecognizer: GestureRecognizerFactoryWithHandlers<
            ReadDependentGestureRecognizer>(
          () => ReadDependentGestureRecognizer(readOnly: readOnly),
          (instance) => instance
            ..onTapUp = ((_) => print('Test'))
        )
      };

      return RawGestureDetector(
        gestures: gestures,
        child: Image.file(snapshot.data),
      );
    }
  );
}

class ReadDependentGestureRecognizer extends TapGestureRecognizer {
  ReadDependentGestureRecognizer({@required this.readOnly});

  final bool readOnly;

  @override
  bool isPointerAllowed(PointerDownEvent event) {
    if (!readOnly) {
      return false;
    }
    return super.isPointerAllowed(event);
  }
}
```

**Explanation of the code:**
When a `PointerDownEvent` is received by the `GestureBinding` a hit
test is performed to determine which `HitTestTarget` nodes are affected.
For this the (I think) element tree is traversed downwards to find
out which elements has been hit. To find out which elements were
hit, the method `hitTestSelf` and `hitTestChildren` are used. Since
the `hitTestChildren` method of `TextLine` has not been implemented 
yet, `false` was always returned, which is why the hit test
never arrived at the `embedBuilder`. With the code change, the hit is
passed on and can be processed correctly in the embed.

Additionally I removed the class `_TransparentTapGestureRecognizer`, 
because this class always accepted the gesture, even if the recognizer 
lost in the arena.
pull/87/head
Till Friebe 4 years ago committed by GitHub
parent e36033929c
commit dda5805935
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      lib/widgets/text_line.dart
  2. 23
      lib/widgets/text_selection.dart

@ -785,6 +785,11 @@ class RenderEditableTextLine extends RenderEditableBox {
);
_cursorPainter.paint(context.canvas, effectiveOffset, position);
}
@override
bool hitTestChildren(BoxHitTestResult result, {Offset position}) {
return this._children.first.hitTest(result, position: position);
}
}
class _TextLineElement extends RenderObjectElement {

@ -670,10 +670,10 @@ class _EditorTextSelectionGestureDetectorState
final Map<Type, GestureRecognizerFactory> gestures =
<Type, GestureRecognizerFactory>{};
gestures[_TransparentTapGestureRecognizer] =
GestureRecognizerFactoryWithHandlers<_TransparentTapGestureRecognizer>(
() => _TransparentTapGestureRecognizer(debugOwner: this),
(_TransparentTapGestureRecognizer instance) {
gestures[TapGestureRecognizer] =
GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
() => TapGestureRecognizer(debugOwner: this),
(TapGestureRecognizer instance) {
instance
..onTapDown = _handleTapDown
..onTapUp = _handleTapUp
@ -735,18 +735,3 @@ class _EditorTextSelectionGestureDetectorState
);
}
}
class _TransparentTapGestureRecognizer extends TapGestureRecognizer {
_TransparentTapGestureRecognizer({
Object debugOwner,
}) : super(debugOwner: debugOwner);
@override
void rejectGesture(int pointer) {
if (state == GestureRecognizerState.ready) {
acceptGesture(pointer);
} else {
super.rejectGesture(pointer);
}
}
}

Loading…
Cancel
Save