diff --git a/README.md b/README.md index 2ca9178fa4..709f454c92 100644 --- a/README.md +++ b/README.md @@ -185,6 +185,7 @@ Once the above issue is resolved, the aforementioned compromises will go away. C | `style` | A powerful API that allows you to customize the style that should be used when rendering a specific HTMl tag. | | `navigationDelegateForIframe` | Allows you to set the `NavigationDelegate` for the `WebView`s of all the iframes rendered by the `Html` widget. | | `customImageRender` | A powerful API that allows you to fully customize how images are loaded. | +| `selectionControls` | A custom text selection controls that allow you to override default toolbar and build toolbar with custom text selection options. See an [example](https://github.com/justinmc/flutter-text-selection-menu-examples/blob/master/lib/custom_menu_page.dart). | ### Getters: diff --git a/lib/flutter_html.dart b/lib/flutter_html.dart index bfcd5068ba..d0a68217ef 100644 --- a/lib/flutter_html.dart +++ b/lib/flutter_html.dart @@ -221,6 +221,7 @@ class SelectableHtml extends StatelessWidget { this.shrinkWrap = false, this.style = const {}, this.tagsList = const [], + this.selectionControls }) : document = null, assert(data != null), _anchorKey = anchorKey ?? GlobalKey(), @@ -236,6 +237,7 @@ class SelectableHtml extends StatelessWidget { this.shrinkWrap = false, this.style = const {}, this.tagsList = const [], + this.selectionControls }) : data = null, assert(document != null), _anchorKey = anchorKey ?? GlobalKey(), @@ -270,6 +272,10 @@ class SelectableHtml extends StatelessWidget { /// An API that allows you to override the default style for any HTML element final Map style; + /// Custom Selection controls allows you to override default toolbar and build custom toolbar + /// options + final TextSelectionControls? selectionControls; + static List get tags => new List.from(SELECTABLE_ELEMENTS); @override @@ -295,6 +301,7 @@ class SelectableHtml extends StatelessWidget { imageRenders: defaultImageRenders, tagsList: tagsList.isEmpty ? SelectableHtml.tags : tagsList, navigationDelegateForIframe: null, + selectionControls: selectionControls, ), ); } diff --git a/lib/html_parser.dart b/lib/html_parser.dart index 715160f2e2..ee7d01f7c6 100644 --- a/lib/html_parser.dart +++ b/lib/html_parser.dart @@ -58,6 +58,7 @@ class HtmlParser extends StatelessWidget { final List tagsList; final NavigationDelegate? navigationDelegateForIframe; final OnTap? _onAnchorTap; + final TextSelectionControls? selectionControls; HtmlParser({ required this.key, @@ -75,6 +76,7 @@ class HtmlParser extends StatelessWidget { required this.imageRenders, required this.tagsList, required this.navigationDelegateForIframe, + this.selectionControls }) : this._onAnchorTap = onAnchorTap != null ? onAnchorTap : key != null @@ -125,6 +127,7 @@ class HtmlParser extends StatelessWidget { tree: cleanedTree, style: cleanedTree.style, ), + selectionControls: selectionControls, ); } return StyledText( @@ -1052,6 +1055,7 @@ class StyledText extends StatelessWidget { final RenderContext renderContext; final AnchorKey? key; final bool _selectable; + final TextSelectionControls? selectionControls; const StyledText({ required this.textSpan, @@ -1059,6 +1063,7 @@ class StyledText extends StatelessWidget { this.textScaleFactor = 1.0, required this.renderContext, this.key, + this.selectionControls, }) : _selectable = false, super(key: key); @@ -1068,6 +1073,7 @@ class StyledText extends StatelessWidget { this.textScaleFactor = 1.0, required this.renderContext, this.key, + this.selectionControls }) : textSpan = textSpan, _selectable = true, super(key: key); @@ -1082,6 +1088,7 @@ class StyledText extends StatelessWidget { textDirection: style.direction, textScaleFactor: textScaleFactor, maxLines: style.maxLines, + selectionControls: selectionControls, ); } return SizedBox(