1+ import 'dart:ui' ;
2+ import 'package:flutter/rendering.dart' ;
3+ import 'package:flutter/widgets.dart' ;
4+
5+ class BackgroundBlur extends SingleChildRenderObjectWidget {
6+ final double radius;
7+
8+ const BackgroundBlur ({
9+ required this .radius,
10+ super .child,
11+ super .key,
12+ });
13+
14+ @override
15+ RenderObject createRenderObject (BuildContext context) {
16+ final renderObject = RenderBackgroundBlur ();
17+ updateRenderObject (context, renderObject);
18+ return renderObject;
19+ }
20+
21+ @override
22+ void updateRenderObject (BuildContext context, RenderBackgroundBlur renderObject) {
23+ renderObject.radius = radius;
24+ }
25+ }
26+
27+ class RenderBackgroundBlur extends RenderProxyBox {
28+ late double radius;
29+
30+ @override
31+ void paint (PaintingContext context, Offset offset) {
32+ if (child == null ) return ;
33+ final bounds = offset & size;
34+
35+ const forceWhite = ColorFilter .matrix (< double > [
36+ 255 , 0 , 0 , 0 , 255 ,
37+ 0 , 255 , 0 , 0 , 255 ,
38+ 0 , 0 , 255 , 0 , 255 ,
39+ 0 , 0 , 0 , 255 , 0 ,
40+ ]);
41+
42+ final maskPaint = Paint ()
43+ ..color = const Color (0xFFFFFFFF )
44+ ..blendMode = BlendMode .dstIn
45+ ..imageFilter = ImageFilter .compose (
46+ inner: forceWhite,
47+ outer: ImageFilter .blur (sigmaX: 1 , sigmaY: 1 ),
48+ )
49+ ;
50+
51+ BackdropFilterLayer backdropFilterLayer = BackdropFilterLayer (
52+ filter: ImageFilter .blur (sigmaX: radius * 0.5 , sigmaY: radius * 0.5 ),
53+ );
54+
55+ // clip the image to optimize multiple backdrop filters on screen:
56+ // https://github.com/flutter/flutter/issues/126353
57+ context.pushClipRect (true , offset, Offset .zero & size, (context, offset) {
58+ // push the backdrop filter
59+ context.pushLayer (backdropFilterLayer, (context, offset) {
60+ // mask the effect based on the children being rendered
61+ context.canvas.saveLayer (bounds, maskPaint);
62+ context.paintChild (child! , offset);
63+ context.canvas.restore ();
64+ }, offset);
65+ });
66+
67+ // paint the original child on top of the effect
68+ // NOTE: The children must be translucent for the effect to be visible
69+ context.paintChild (child! , offset);
70+ }
71+ }
0 commit comments