diff --git a/README.md b/README.md index cfe891b2bd..dc4fd6d603 100644 --- a/README.md +++ b/README.md @@ -175,4 +175,7 @@ until official support is added. padding: EdgeInsets.all(8.0), backgroundColor: Colors.white70, defaultTextStyle: TextStyle(color: Colors.black), + onLinkTap: (url) { + // open url in a webview + } ) \ No newline at end of file diff --git a/lib/flutter_html.dart b/lib/flutter_html.dart index 85b02ead92..e8abe70f91 100644 --- a/lib/flutter_html.dart +++ b/lib/flutter_html.dart @@ -9,13 +9,15 @@ class Html extends StatelessWidget { @required this.data, this.padding, this.backgroundColor, - this.defaultTextStyle = const TextStyle(color: Colors.black)}) + this.defaultTextStyle = const TextStyle(color: Colors.black), + this.onLinkTap}) : super(key: key); final String data; final EdgeInsetsGeometry padding; final Color backgroundColor; final TextStyle defaultTextStyle; + final Function onLinkTap; @override Widget build(BuildContext context) { @@ -24,7 +26,7 @@ class Html extends StatelessWidget { color: backgroundColor, child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: HtmlParser(defaultTextStyle: defaultTextStyle).parse(data), + children: HtmlParser(defaultTextStyle: defaultTextStyle, onLinkTap: onLinkTap).parse(data), ), ); } diff --git a/lib/html_parser.dart b/lib/html_parser.dart index 11811ca921..704b26abe3 100644 --- a/lib/html_parser.dart +++ b/lib/html_parser.dart @@ -3,9 +3,13 @@ import 'package:html/parser.dart' as parser; import 'package:html/dom.dart' as dom; class HtmlParser { - HtmlParser({this.defaultTextStyle = const TextStyle(color: Colors.black)}); + HtmlParser({ + this.defaultTextStyle = const TextStyle(color: Colors.black), + this.onLinkTap + }); final TextStyle defaultTextStyle; + final Function onLinkTap; static const _supportedElements = [ "a", @@ -92,18 +96,27 @@ class HtmlParser { } switch (node.localName) { case "a": - return RichText( + return GestureDetector( + child: RichText( text: TextSpan( - children: [ - TextSpan( - children: _parseInlineElement(node), - style: TextStyle( - decoration: TextDecoration.underline, - ), - ) - ], - style: defaultTextStyle, - )); + children: [ + TextSpan( + children: _parseInlineElement(node), + style: TextStyle( + decoration: TextDecoration.underline, + ), + ) + ], + style: defaultTextStyle, + ), + ), + onTap: () { + if (node.attributes.containsKey('href')) { + String url = node.attributes['href']; + onLinkTap(url); + } + } + ); case "abbr": return RichText( text: TextSpan( @@ -440,11 +453,13 @@ class HtmlParser { crossAxisAlignment: CrossAxisAlignment.start, ); case "p": - return RichText( - text: TextSpan( - children: _parseInlineElement(node), - style: defaultTextStyle, - )); + return Padding( + padding: EdgeInsets.only(top: 14.0, bottom: 14.0), + child: Column( + children: _parseNodeList(node.nodes), + crossAxisAlignment: CrossAxisAlignment.start, + ), + ); case "pre": return Padding( padding: const EdgeInsets.only(top: 14.0, bottom: 14.0),