From a82acf18cf9949f1cf50ea7fe4d08357d7c6295a Mon Sep 17 00:00:00 2001 From: Lee Higgins Date: Sat, 12 Oct 2019 13:57:32 +0200 Subject: [PATCH] Added a custom function for creating image widgets --- lib/flutter_html.dart | 3 ++ lib/rich_text_parser.dart | 107 ++++++++++++++++++++++++-------------- 2 files changed, 72 insertions(+), 38 deletions(-) diff --git a/lib/flutter_html.dart b/lib/flutter_html.dart index a58ba80f20..77f1608218 100644 --- a/lib/flutter_html.dart +++ b/lib/flutter_html.dart @@ -30,6 +30,7 @@ class Html extends StatelessWidget { this.imageProperties, this.onImageTap, this.showImages = true, + this.customImgRender, }) : super(key: key); final String data; @@ -43,6 +44,7 @@ class Html extends StatelessWidget { final ImageErrorListener onImageError; final TextStyle linkStyle; final bool shrinkToFit; + final ImgRender customImgRender; /// Properties for the Image widget that gets rendered by the rich text parser final ImageProperties imageProperties; @@ -80,6 +82,7 @@ class Html extends StatelessWidget { imageProperties: imageProperties, onImageTap: onImageTap, showImages: showImages, + customImageRenderer: customImgRender, ) : HtmlOldParser( width: width, diff --git a/lib/rich_text_parser.dart b/lib/rich_text_parser.dart index 25258e2ae1..c13a12ad5d 100644 --- a/lib/rich_text_parser.dart +++ b/lib/rich_text_parser.dart @@ -7,6 +7,16 @@ import 'package:html/parser.dart' as parser; import 'image_properties.dart'; +typedef ImgRender = Widget Function({ + String src, + String alt, + double width, + double height, + ImageProperties imageProperties, + bool shrinkToFit, + ParseContext nextContext, +}); + typedef CustomRender = Widget Function(dom.Node node, List children); typedef CustomTextStyle = TextStyle Function( dom.Node node, @@ -20,6 +30,51 @@ typedef OnImageTap = void Function(String source); const OFFSET_TAGS_FONT_SIZE_FACTOR = 0.7; //The ratio of the parent font for each of the offset tags: sup or sub +ImgRender _defaultImageRenderer = ( + {String src, + String alt, + double width, + double height, + ImageProperties imageProperties, + bool shrinkToFit, + ParseContext nextContext}) { + return Image.network( + src, + frameBuilder: (context, child, frame, _) { + if (alt != null && frame == null) { + return BlockText( + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + text: alt, + style: nextContext.childStyle, + ), + ), + shrinkToFit: shrinkToFit, + ); + } + if (frame != null) { + return child; + } + return Container(); + }, + width: (width ?? -1) > 0 ? width : null, + height: (height ?? -1) > 0 ? height : null, + scale: imageProperties?.scale ?? 1.0, + matchTextDirection: imageProperties?.matchTextDirection ?? false, + centerSlice: imageProperties?.centerSlice, + filterQuality: imageProperties?.filterQuality ?? FilterQuality.low, + alignment: imageProperties?.alignment ?? Alignment.center, + colorBlendMode: imageProperties?.colorBlendMode, + fit: imageProperties?.fit, + color: imageProperties?.color, + repeat: imageProperties?.repeat ?? ImageRepeat.noRepeat, + semanticLabel: imageProperties?.semanticLabel, + excludeFromSemantics: + (imageProperties?.semanticLabel == null) ? true : false, + ); +}; + class LinkTextSpan extends TextSpan { // Beware! // @@ -165,6 +220,7 @@ class HtmlRichTextParser extends StatelessWidget { this.imageProperties, this.onImageTap, this.showImages = true, + this.customImageRenderer, }); final double indentSize = 10.0; @@ -181,6 +237,7 @@ class HtmlRichTextParser extends StatelessWidget { final ImageProperties imageProperties; final OnImageTap onImageTap; final bool showImages; + final ImgRender customImageRenderer; // style elements set a default style // for all child nodes @@ -794,45 +851,19 @@ class HtmlRichTextParser extends StatelessWidget { onError: onImageError ?? (_, __) {}, ); parseContext.rootWidgetList.add(GestureDetector( - child: Image.network( - node.attributes['src'], - frameBuilder: (context, child, frame, _) { - if (node.attributes['alt'] != null && frame == null) { - return BlockText( - child: RichText( - textAlign: TextAlign.center, - text: TextSpan( - text: node.attributes['alt'], - style: nextContext.childStyle, - ), - ), + child: customImageRenderer( + src: node.attributes['src'], + alt: node.attributes['alt'], + imageProperties: imageProperties, + shrinkToFit: shrinkToFit, + nextContext: nextContext, + ) ?? + _defaultImageRenderer( + src: node.attributes['src'], + alt: node.attributes['alt'], + imageProperties: imageProperties, shrinkToFit: shrinkToFit, - ); - } - if (frame != null) { - return child; - } - return Container(); - }, - width: (width ?? -1) > 0 ? width : null, - height: (height ?? -1) > 0 ? height : null, - scale: imageProperties?.scale ?? 1.0, - matchTextDirection: - imageProperties?.matchTextDirection ?? false, - centerSlice: imageProperties?.centerSlice, - filterQuality: - imageProperties?.filterQuality ?? FilterQuality.low, - alignment: imageProperties?.alignment ?? Alignment.center, - colorBlendMode: imageProperties?.colorBlendMode, - fit: imageProperties?.fit, - color: imageProperties?.color, - repeat: imageProperties?.repeat ?? ImageRepeat.noRepeat, - semanticLabel: imageProperties?.semanticLabel, - excludeFromSemantics: - (imageProperties?.semanticLabel == null) - ? true - : false, - ), + nextContext: nextContext), onTap: () { if (onImageTap != null) { onImageTap(node.attributes['src']);