add custom recognizer

pull/1196/head
jiangchong 2 years ago
parent 06cafef8c9
commit 917adb2d1f
  1. 2
      lib/src/widgets/delegate.dart
  2. 3
      lib/src/widgets/editor.dart
  3. 3
      lib/src/widgets/raw_editor.dart
  4. 30
      lib/src/widgets/text_line.dart

@ -14,6 +14,8 @@ typedef EmbedsBuilder = EmbedBuilder Function(Embed node);
typedef CustomStyleBuilder = TextStyle Function(Attribute attribute); typedef CustomStyleBuilder = TextStyle Function(Attribute attribute);
typedef CustomRecognizerBuilder = GestureRecognizer? Function(Attribute attribute);
/// Delegate interface for the [EditorTextSelectionGestureDetectorBuilder]. /// Delegate interface for the [EditorTextSelectionGestureDetectorBuilder].
/// ///
/// The interface is usually implemented by textfield implementations wrapping /// The interface is usually implemented by textfield implementations wrapping

@ -176,6 +176,7 @@ class QuillEditor extends StatefulWidget {
this.unknownEmbedBuilder, this.unknownEmbedBuilder,
this.linkActionPickerDelegate = defaultLinkActionPickerDelegate, this.linkActionPickerDelegate = defaultLinkActionPickerDelegate,
this.customStyleBuilder, this.customStyleBuilder,
this.customRecognizerBuilder,
this.locale, this.locale,
this.floatingCursorDisabled = false, this.floatingCursorDisabled = false,
this.textSelectionControls, this.textSelectionControls,
@ -372,6 +373,7 @@ class QuillEditor extends StatefulWidget {
final Iterable<EmbedBuilder>? embedBuilders; final Iterable<EmbedBuilder>? embedBuilders;
final EmbedBuilder? unknownEmbedBuilder; final EmbedBuilder? unknownEmbedBuilder;
final CustomStyleBuilder? customStyleBuilder; final CustomStyleBuilder? customStyleBuilder;
final CustomRecognizerBuilder? customRecognizerBuilder;
/// The locale to use for the editor toolbar, defaults to system locale /// The locale to use for the editor toolbar, defaults to system locale
/// More https://github.com/singerdmx/flutter-quill#translation /// More https://github.com/singerdmx/flutter-quill#translation
@ -518,6 +520,7 @@ class QuillEditorState extends State<QuillEditor>
embedBuilder: _getEmbedBuilder, embedBuilder: _getEmbedBuilder,
linkActionPickerDelegate: widget.linkActionPickerDelegate, linkActionPickerDelegate: widget.linkActionPickerDelegate,
customStyleBuilder: widget.customStyleBuilder, customStyleBuilder: widget.customStyleBuilder,
customRecognizerBuilder: widget.customRecognizerBuilder,
floatingCursorDisabled: widget.floatingCursorDisabled, floatingCursorDisabled: widget.floatingCursorDisabled,
onImagePaste: widget.onImagePaste, onImagePaste: widget.onImagePaste,
customShortcuts: widget.customShortcuts, customShortcuts: widget.customShortcuts,

@ -79,6 +79,7 @@ class RawEditor extends StatefulWidget {
this.scrollPhysics, this.scrollPhysics,
this.linkActionPickerDelegate = defaultLinkActionPickerDelegate, this.linkActionPickerDelegate = defaultLinkActionPickerDelegate,
this.customStyleBuilder, this.customStyleBuilder,
this.customRecognizerBuilder,
this.floatingCursorDisabled = false, this.floatingCursorDisabled = false,
this.onImagePaste, this.onImagePaste,
this.customLinkPrefixes = const <String>[], this.customLinkPrefixes = const <String>[],
@ -262,6 +263,7 @@ class RawEditor extends StatefulWidget {
final EmbedsBuilder embedBuilder; final EmbedsBuilder embedBuilder;
final LinkActionPickerDelegate linkActionPickerDelegate; final LinkActionPickerDelegate linkActionPickerDelegate;
final CustomStyleBuilder? customStyleBuilder; final CustomStyleBuilder? customStyleBuilder;
final CustomRecognizerBuilder? customRecognizerBuilder;
final bool floatingCursorDisabled; final bool floatingCursorDisabled;
final List<String> customLinkPrefixes; final List<String> customLinkPrefixes;
@ -925,6 +927,7 @@ class RawEditorState extends EditorState
textDirection: _textDirection, textDirection: _textDirection,
embedBuilder: widget.embedBuilder, embedBuilder: widget.embedBuilder,
customStyleBuilder: widget.customStyleBuilder, customStyleBuilder: widget.customStyleBuilder,
customRecognizerBuilder: widget.customRecognizerBuilder,
styles: _styles!, styles: _styles!,
readOnly: widget.readOnly, readOnly: widget.readOnly,
controller: controller, controller: controller,

@ -41,6 +41,7 @@ class TextLine extends StatefulWidget {
required this.linkActionPicker, required this.linkActionPicker,
this.textDirection, this.textDirection,
this.customStyleBuilder, this.customStyleBuilder,
this.customRecognizerBuilder,
this.customLinkPrefixes = const <String>[], this.customLinkPrefixes = const <String>[],
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -52,6 +53,7 @@ class TextLine extends StatefulWidget {
final bool readOnly; final bool readOnly;
final QuillController controller; final QuillController controller;
final CustomStyleBuilder? customStyleBuilder; final CustomStyleBuilder? customStyleBuilder;
final CustomRecognizerBuilder? customRecognizerBuilder;
final ValueChanged<String>? onLaunchUrl; final ValueChanged<String>? onLaunchUrl;
final LinkActionPicker linkActionPicker; final LinkActionPicker linkActionPicker;
final List<String> customLinkPrefixes; final List<String> customLinkPrefixes;
@ -313,12 +315,14 @@ class _TextLineState extends State<TextLine> {
final isLink = nodeStyle.containsKey(Attribute.link.key) && final isLink = nodeStyle.containsKey(Attribute.link.key) &&
nodeStyle.attributes[Attribute.link.key]!.value != null; nodeStyle.attributes[Attribute.link.key]!.value != null;
final GestureRecognizer? recognizer = _getRecognizer(node, isLink);
return TextSpan( return TextSpan(
text: textNode.value, text: textNode.value,
style: _getInlineTextStyle( style: _getInlineTextStyle(
textNode, defaultStyles, nodeStyle, lineStyle, isLink), textNode, defaultStyles, nodeStyle, lineStyle, isLink),
recognizer: isLink && canLaunchLinks ? _getRecognizer(node) : null, recognizer: recognizer,
mouseCursor: isLink && canLaunchLinks ? SystemMouseCursors.click : null, mouseCursor: (recognizer != null) ? SystemMouseCursors.click : null,
); );
} }
@ -406,11 +410,28 @@ class _TextLineState extends State<TextLine> {
return res; return res;
} }
GestureRecognizer _getRecognizer(Node segment) { GestureRecognizer? _getRecognizer(Node segment, bool isLink) {
if (_linkRecognizers.containsKey(segment)) { if (_linkRecognizers.containsKey(segment)) {
return _linkRecognizers[segment]!; return _linkRecognizers[segment]!;
} }
if (widget.customRecognizerBuilder != null) {
final textNode = segment as leaf.Text;
final nodeStyle = textNode.style;
for (String key in nodeStyle.attributes.keys) {
final attr = nodeStyle.attributes[key];
if (attr != null) {
GestureRecognizer? recognizer = widget.customRecognizerBuilder!.call(attr);
if (recognizer != null) {
_linkRecognizers[segment] = recognizer!;
return recognizer;
}
}
}
}
if (isLink && canLaunchLinks) {
if (isDesktop() || widget.readOnly) { if (isDesktop() || widget.readOnly) {
_linkRecognizers[segment] = TapGestureRecognizer() _linkRecognizers[segment] = TapGestureRecognizer()
..onTap = () => _tapNodeLink(segment); ..onTap = () => _tapNodeLink(segment);
@ -418,7 +439,8 @@ class _TextLineState extends State<TextLine> {
_linkRecognizers[segment] = LongPressGestureRecognizer() _linkRecognizers[segment] = LongPressGestureRecognizer()
..onLongPress = () => _longPressLink(segment); ..onLongPress = () => _longPressLink(segment);
} }
return _linkRecognizers[segment]!; }
return _linkRecognizers[segment];
} }
Future<void> _launchUrl(String url) async { Future<void> _launchUrl(String url) async {

Loading…
Cancel
Save