@@ -11,6 +11,19 @@ import 'framework.dart';
1111
1212/// Applies an [ImageFilter] to its child.
1313///
14+ /// An image filter will always apply its filter operation to the child widget,
15+ /// even if said filter is conceptually a "no-op", such as an ImageFilter.blur
16+ /// with a radius of 0 or an ImageFilter.matrix with an identity matrix. Setting
17+ /// [ImageFiltered.enabled] to `false` is a more efficient manner of disabling
18+ /// an image filter.
19+ ///
20+ /// The framework does not attempt to optimize out "no-op" filters because it
21+ /// cannot tell the difference between an intentional no-op and a filter that is
22+ /// only incidentally a no-op. Consider an ImageFilter.matrix that is animated
23+ /// and happens to pass through the identity matrix. If the framework identified it
24+ /// as a no-op it would drop and then recreate the layer during the animation which
25+ /// would be more expensive than keeping it around.
26+ ///
1427/// {@youtube 560 315 https://www.youtube.com/watch?v=7Lftorq4i2o}
1528///
1629/// See also:
@@ -27,17 +40,27 @@ class ImageFiltered extends SingleChildRenderObjectWidget {
2740 super .key,
2841 required this .imageFilter,
2942 super .child,
43+ this .enabled = true ,
3044 }) : assert (imageFilter != null );
3145
3246 /// The image filter to apply to the child of this widget.
3347 final ImageFilter imageFilter;
3448
49+ /// Whether or not to apply the image filter opation to the child of this
50+ /// widget.
51+ ///
52+ /// Prefer setting enabled to `false` instead of creating a "no-op" filter
53+ /// type for performance reasons.
54+ final bool enabled;
55+
3556 @override
36- RenderObject createRenderObject (BuildContext context) => _ImageFilterRenderObject (imageFilter);
57+ RenderObject createRenderObject (BuildContext context) => _ImageFilterRenderObject (imageFilter, enabled );
3758
3859 @override
3960 void updateRenderObject (BuildContext context, RenderObject renderObject) {
40- (renderObject as _ImageFilterRenderObject ).imageFilter = imageFilter;
61+ (renderObject as _ImageFilterRenderObject )
62+ ..enabled = enabled
63+ ..imageFilter = imageFilter;
4164 }
4265
4366 @override
@@ -48,7 +71,17 @@ class ImageFiltered extends SingleChildRenderObjectWidget {
4871}
4972
5073class _ImageFilterRenderObject extends RenderProxyBox {
51- _ImageFilterRenderObject (this ._imageFilter);
74+ _ImageFilterRenderObject (this ._imageFilter, this ._enabled);
75+
76+ bool get enabled => _enabled;
77+ bool _enabled;
78+ set enabled (bool value) {
79+ if (enabled == value) {
80+ return ;
81+ }
82+ _enabled = value;
83+ markNeedsPaint ();
84+ }
5285
5386 ImageFilter get imageFilter => _imageFilter;
5487 ImageFilter _imageFilter;
@@ -61,11 +94,16 @@ class _ImageFilterRenderObject extends RenderProxyBox {
6194 }
6295
6396 @override
64- bool get alwaysNeedsCompositing => child != null ;
97+ bool get alwaysNeedsCompositing => child != null && enabled ;
6598
6699 @override
67100 void paint (PaintingContext context, Offset offset) {
68101 assert (imageFilter != null );
102+ if (! enabled) {
103+ layer = null ;
104+ return super .paint (context, offset);
105+ }
106+
69107 if (layer == null ) {
70108 layer = ImageFilterLayer (imageFilter: imageFilter);
71109 } else {
0 commit comments