Skip to content
4 changes: 4 additions & 0 deletions packages/vector_graphics/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.2.0

* Adds `imageBuilder` property to `VectorGraphic` for wrapping the loaded vector graphic widget.

## 1.1.21

* Corrected width/height parameter documentation in VectorGraphic widget.
Expand Down
20 changes: 20 additions & 0 deletions packages/vector_graphics/lib/src/vector_graphics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ enum RenderingStrategy {
typedef VectorGraphicsErrorWidget =
Widget Function(BuildContext context, Object error, StackTrace stackTrace);

/// The signature that [VectorGraphic.imageBuilder] uses to wrap the
/// successfully loaded vector graphic widget.
typedef VectorGraphicsImageWidget =
Widget Function(BuildContext context, Widget child);

/// A vector graphic/flutter_svg compatibility shim.
VectorGraphic createCompatVectorGraphic({
Key? key,
Expand All @@ -61,6 +66,7 @@ VectorGraphic createCompatVectorGraphic({
Duration? transitionDuration,
WidgetBuilder? placeholderBuilder,
VectorGraphicsErrorWidget? errorBuilder,
VectorGraphicsImageWidget? imageBuilder,
ColorFilter? colorFilter,
Animation<double>? opacity,
RenderingStrategy strategy = RenderingStrategy.picture,
Expand All @@ -80,6 +86,7 @@ VectorGraphic createCompatVectorGraphic({
transitionDuration: transitionDuration,
placeholderBuilder: placeholderBuilder,
errorBuilder: errorBuilder,
imageBuilder: imageBuilder,
colorFilter: colorFilter,
opacity: opacity,
strategy: strategy,
Expand Down Expand Up @@ -120,6 +127,7 @@ class VectorGraphic extends StatefulWidget {
this.transitionDuration,
this.placeholderBuilder,
this.errorBuilder,
this.imageBuilder,
this.colorFilter,
this.opacity,
this.clipViewbox = true,
Expand All @@ -140,6 +148,7 @@ class VectorGraphic extends StatefulWidget {
this.transitionDuration,
this.placeholderBuilder,
this.errorBuilder,
this.imageBuilder,
this.colorFilter,
this.opacity,
this.strategy = RenderingStrategy.picture,
Expand Down Expand Up @@ -219,6 +228,13 @@ class VectorGraphic extends StatefulWidget {
/// A callback that fires if some exception happens during data acquisition or decoding.
final VectorGraphicsErrorWidget? errorBuilder;

/// A builder that wraps the successfully loaded vector graphic widget.
///
/// This builder is only called when the vector graphic has been successfully
/// loaded and is ready to be painted. It can be used to apply decorations
/// such as borders or shadows only when the image is available.
final VectorGraphicsImageWidget? imageBuilder;

/// Set transition duration while switching from placeholder to url image
final Duration? transitionDuration;

Expand Down Expand Up @@ -514,6 +530,10 @@ class _VectorGraphicWidgetState extends State<VectorGraphic> {
if (width != null && height != null) {
child = SizedBox(width: width, height: height, child: child);
}

if (widget.imageBuilder != null) {
child = widget.imageBuilder!(context, child);
}
} else if (_error != null && widget.errorBuilder != null) {
child = widget.errorBuilder!(
context,
Expand Down
1 change: 1 addition & 0 deletions packages/vector_graphics/lib/vector_graphics_compat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ export 'src/vector_graphics.dart'
RenderingStrategy,
VectorGraphic,
VectorGraphicUtilities,
VectorGraphicsImageWidget,
createCompatVectorGraphic,
vg;
2 changes: 1 addition & 1 deletion packages/vector_graphics/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: vector_graphics
description: A vector graphics rendering package for Flutter using a binary encoding.
repository: https://github.com/flutter/packages/tree/main/packages/vector_graphics
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+vector_graphics%22
version: 1.1.21
version: 1.2.0

environment:
sdk: ^3.9.0
Expand Down
64 changes: 64 additions & 0 deletions packages/vector_graphics/test/vector_graphics_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,70 @@ void main() {
expect(matrix.row1.y, 1);
});

testWidgets('imageBuilder wraps the loaded vector graphic', (
WidgetTester tester,
) async {
final buffer = VectorGraphicsBuffer();
codec.writeSize(buffer, 100, 200);
final ByteData data = buffer.done();

await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: VectorGraphic(
loader: TestBytesLoader(data),
imageBuilder: (BuildContext context, Widget child) {
return Container(
key: const ValueKey<String>('image-builder'),
child: child,
);
},
),
),
);
await tester.pumpAndSettle();

expect(find.byKey(const ValueKey<String>('image-builder')), findsOneWidget);
});

testWidgets('imageBuilder is not called during placeholder state', (
WidgetTester tester,
) async {
final completer = Completer<ByteData>();

await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: VectorGraphic(
loader: DelayedBytesLoader(completer.future),
imageBuilder: (BuildContext context, Widget child) {
return Container(
key: const ValueKey<String>('image-builder'),
child: child,
);
},
placeholderBuilder: (BuildContext context) {
return Container(key: const ValueKey<String>('placeholder'));
},
),
),
);

// During loading: placeholder visible, imageBuilder not called
expect(find.byKey(const ValueKey<String>('placeholder')), findsOneWidget);
expect(find.byKey(const ValueKey<String>('image-builder')), findsNothing);

// Complete loading
final buffer = VectorGraphicsBuffer();
codec.writeSize(buffer, 100, 200);
completer.complete(buffer.done());
await tester.pumpAndSettle();

// After loading: imageBuilder visible, placeholder gone
expect(find.byKey(const ValueKey<String>('image-builder')), findsOneWidget);
expect(find.byKey(const ValueKey<String>('placeholder')), findsNothing);
});

testWidgets('VectorGraphicsWidget can handle errors from bytes loader', (
WidgetTester tester,
) async {
Expand Down
Loading