mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
The backdrop key functionality allows multiple backdrop filters to share the same input filter, dramatically improving raster performance. This is only supported on the Impeller backend. The backdrop key class allocates a new int from a static and passes this to the engine layer. with 64 bit integers, we can allocate many backdrop filter ids per frame and never run out. See also: https://github.com/flutter/flutter/issues/156455 ```dart import 'dart:math'; import 'dart:ui'; import 'package:flutter/material.dart'; final _random = Random(); void main() => runApp(const BackdropFilterDemo()); class BackdropFilterDemo extends StatelessWidget { const BackdropFilterDemo({super.key}); static final listKey = BackdropKey(); static final overlayKey = BackdropKey(); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( backgroundColor: Colors.white, body: Stack( children: [ ListView.builder( itemCount: 120, // 60 pairs of red and blue containers itemBuilder: (context, index) { return Container( height: 100, color: index % 2 == 0 ? Colors.red : Colors.blue, ); }, ), Center( child: Container( width: 400, height: 400, decoration: BoxDecoration( border: Border.all(color: Colors.black), ), child: Image.network('https://picsum.photos/400'), ), ), ListView.separated( separatorBuilder: (_, __) => const SizedBox(height: 8), itemBuilder: (context, index) => BlurEffect( backdropKey: listKey, child: SizedBox( height: 50, child: Center( child: Text(index.toString(), style: const TextStyle(color: Colors.white)), ), ), ), itemCount: 200, ), Positioned.fill( bottom: null, child: BlurEffect( backdropKey: overlayKey, child: Padding( padding: EdgeInsets.only( top: MediaQuery.of(context).viewPadding.top, ), child: const SizedBox(height: 45), ), ), ), Positioned.fill( top: null, child: BlurEffect( backdropKey: overlayKey, child: Padding( padding: EdgeInsets.only( top: MediaQuery.of(context).viewPadding.bottom, ), child: const SizedBox(height: 50), ), ), ), ], ), ), ); } } class BlurEffect extends StatelessWidget { final Widget child; const BlurEffect({ required this.child, required this.backdropKey, super.key, }); final BackdropKey backdropKey; @override Widget build(BuildContext context) { return ClipRect( child: BackdropFilter( backdropKey: backdropKey, filter: ImageFilter.blur( sigmaX: 40, sigmaY: 40, // tileMode: TileMode.mirror, ), child: DecoratedBox( decoration: BoxDecoration(color: Colors.black.withOpacity(.65)), child: child, ), ), ); } } ``` ### Skia <img src="https://github.com/user-attachments/assets/4c08e92d-f0ba-42b2-a4c4-fc44efbcfae0" width="200"/> ### Impeller <img src="https://github.com/user-attachments/assets/21e95efd-5e0c-4f41-8f84-af3f0e47d1aa" width="200"/>