Skip to content

Commit ce623f5

Browse files
authored
[vector_graphics] add imageBuilder property to VectorGraphic (#11094)
related with flutter/flutter#182635 Adding an `imageBuilder` property to `VectorGraphic` allows developers to wrap the successfully loaded vector graphic with decorations or interaction layers (e.g., borders, shadows, gesture detectors) only when the image is available. This completes the builder pattern alongside the existing `placeholderBuilder` and `errorBuilder`, giving full control over all three rendering states. ## Changes - Added `VectorGraphicsImageWidget` typedef - Added optional `imageBuilder` parameter to `VectorGraphic` constructors and `createCompatVectorGraphic` - Exported `VectorGraphicsImageWidget` from `vector_graphics_compat.dart` - Added two tests verifying `imageBuilder` is called on success and not during placeholder state - Bumped version to 1.1.20 ## Test plan - [x] `imageBuilder wraps the loaded vector graphic` — verifies the builder is applied on successful load - [x] `imageBuilder is not called during placeholder state` — verifies the builder is skipped during loading - [x] All 60 existing tests pass
1 parent cb91e6d commit ce623f5

5 files changed

Lines changed: 90 additions & 1 deletion

File tree

packages/vector_graphics/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 1.2.0
2+
3+
* Adds `imageBuilder` property to `VectorGraphic` for wrapping the loaded vector graphic widget.
4+
15
## 1.1.21
26

37
* Corrected width/height parameter documentation in VectorGraphic widget.

packages/vector_graphics/lib/src/vector_graphics.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ enum RenderingStrategy {
4747
typedef VectorGraphicsErrorWidget =
4848
Widget Function(BuildContext context, Object error, StackTrace stackTrace);
4949

50+
/// The signature that [VectorGraphic.imageBuilder] uses to wrap the
51+
/// successfully loaded vector graphic widget.
52+
typedef VectorGraphicsImageWidget =
53+
Widget Function(BuildContext context, Widget child);
54+
5055
/// A vector graphic/flutter_svg compatibility shim.
5156
VectorGraphic createCompatVectorGraphic({
5257
Key? key,
@@ -61,6 +66,7 @@ VectorGraphic createCompatVectorGraphic({
6166
Duration? transitionDuration,
6267
WidgetBuilder? placeholderBuilder,
6368
VectorGraphicsErrorWidget? errorBuilder,
69+
VectorGraphicsImageWidget? imageBuilder,
6470
ColorFilter? colorFilter,
6571
Animation<double>? opacity,
6672
RenderingStrategy strategy = RenderingStrategy.picture,
@@ -80,6 +86,7 @@ VectorGraphic createCompatVectorGraphic({
8086
transitionDuration: transitionDuration,
8187
placeholderBuilder: placeholderBuilder,
8288
errorBuilder: errorBuilder,
89+
imageBuilder: imageBuilder,
8390
colorFilter: colorFilter,
8491
opacity: opacity,
8592
strategy: strategy,
@@ -120,6 +127,7 @@ class VectorGraphic extends StatefulWidget {
120127
this.transitionDuration,
121128
this.placeholderBuilder,
122129
this.errorBuilder,
130+
this.imageBuilder,
123131
this.colorFilter,
124132
this.opacity,
125133
this.clipViewbox = true,
@@ -140,6 +148,7 @@ class VectorGraphic extends StatefulWidget {
140148
this.transitionDuration,
141149
this.placeholderBuilder,
142150
this.errorBuilder,
151+
this.imageBuilder,
143152
this.colorFilter,
144153
this.opacity,
145154
this.strategy = RenderingStrategy.picture,
@@ -219,6 +228,13 @@ class VectorGraphic extends StatefulWidget {
219228
/// A callback that fires if some exception happens during data acquisition or decoding.
220229
final VectorGraphicsErrorWidget? errorBuilder;
221230

231+
/// A builder that wraps the successfully loaded vector graphic widget.
232+
///
233+
/// This builder is only called when the vector graphic has been successfully
234+
/// loaded and is ready to be painted. It can be used to apply decorations
235+
/// such as borders or shadows only when the image is available.
236+
final VectorGraphicsImageWidget? imageBuilder;
237+
222238
/// Set transition duration while switching from placeholder to url image
223239
final Duration? transitionDuration;
224240

@@ -514,6 +530,10 @@ class _VectorGraphicWidgetState extends State<VectorGraphic> {
514530
if (width != null && height != null) {
515531
child = SizedBox(width: width, height: height, child: child);
516532
}
533+
534+
if (widget.imageBuilder != null) {
535+
child = widget.imageBuilder!(context, child);
536+
}
517537
} else if (_error != null && widget.errorBuilder != null) {
518538
child = widget.errorBuilder!(
519539
context,

packages/vector_graphics/lib/vector_graphics_compat.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ export 'src/vector_graphics.dart'
1111
RenderingStrategy,
1212
VectorGraphic,
1313
VectorGraphicUtilities,
14+
VectorGraphicsImageWidget,
1415
createCompatVectorGraphic,
1516
vg;

packages/vector_graphics/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: vector_graphics
22
description: A vector graphics rendering package for Flutter using a binary encoding.
33
repository: https://github.com/flutter/packages/tree/main/packages/vector_graphics
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+vector_graphics%22
5-
version: 1.1.21
5+
version: 1.2.0
66

77
environment:
88
sdk: ^3.9.0

packages/vector_graphics/test/vector_graphics_test.dart

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,70 @@ void main() {
775775
expect(matrix.row1.y, 1);
776776
});
777777

778+
testWidgets('imageBuilder wraps the loaded vector graphic', (
779+
WidgetTester tester,
780+
) async {
781+
final buffer = VectorGraphicsBuffer();
782+
codec.writeSize(buffer, 100, 200);
783+
final ByteData data = buffer.done();
784+
785+
await tester.pumpWidget(
786+
Directionality(
787+
textDirection: TextDirection.ltr,
788+
child: VectorGraphic(
789+
loader: TestBytesLoader(data),
790+
imageBuilder: (BuildContext context, Widget child) {
791+
return Container(
792+
key: const ValueKey<String>('image-builder'),
793+
child: child,
794+
);
795+
},
796+
),
797+
),
798+
);
799+
await tester.pumpAndSettle();
800+
801+
expect(find.byKey(const ValueKey<String>('image-builder')), findsOneWidget);
802+
});
803+
804+
testWidgets('imageBuilder is not called during placeholder state', (
805+
WidgetTester tester,
806+
) async {
807+
final completer = Completer<ByteData>();
808+
809+
await tester.pumpWidget(
810+
Directionality(
811+
textDirection: TextDirection.ltr,
812+
child: VectorGraphic(
813+
loader: DelayedBytesLoader(completer.future),
814+
imageBuilder: (BuildContext context, Widget child) {
815+
return Container(
816+
key: const ValueKey<String>('image-builder'),
817+
child: child,
818+
);
819+
},
820+
placeholderBuilder: (BuildContext context) {
821+
return Container(key: const ValueKey<String>('placeholder'));
822+
},
823+
),
824+
),
825+
);
826+
827+
// During loading: placeholder visible, imageBuilder not called
828+
expect(find.byKey(const ValueKey<String>('placeholder')), findsOneWidget);
829+
expect(find.byKey(const ValueKey<String>('image-builder')), findsNothing);
830+
831+
// Complete loading
832+
final buffer = VectorGraphicsBuffer();
833+
codec.writeSize(buffer, 100, 200);
834+
completer.complete(buffer.done());
835+
await tester.pumpAndSettle();
836+
837+
// After loading: imageBuilder visible, placeholder gone
838+
expect(find.byKey(const ValueKey<String>('image-builder')), findsOneWidget);
839+
expect(find.byKey(const ValueKey<String>('placeholder')), findsNothing);
840+
});
841+
778842
testWidgets('VectorGraphicsWidget can handle errors from bytes loader', (
779843
WidgetTester tester,
780844
) async {

0 commit comments

Comments
 (0)