Flutter中Stack内BackdropFilter始终显示问题求助
问题:列表中使用BackdropFilter实现图片加载模糊效果异常
我尝试在列表中使用BackdropFilter实现图片加载时的自定义模糊效果,代码如下:
class MediaOpned extends ConsumerStatefulWidget { const MediaOpned({ Key? key, }) : super(key: key); @override ConsumerState<MediaOpned> createState() => _MediaOpnedState(); } class _MediaOpnedState extends ConsumerState<MediaOpned> { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, body: ListView.builder( itemCount: 5, itemBuilder: (BuildContext context, int index) { return Stack( children: [ BackdropFilter( filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: Container( color: Colors.grey, width: double.infinity, height: imageHieght, ), ), CachedNetworkImage( imageUrl: 'https://evrak.co/uploads/images/2022/10/UvpXJ.webp', fit: BoxFit.cover , ), ], ); }, ) ); } }
但问题是,当图片加载完成后,模糊层仍可见。仅当itemCount大于1时会出现该问题;若itemCount为1,图片加载后会完全覆盖模糊层,符合预期。请问如何解决该异常?
解决方案
问题根源
BackdropFilter的模糊效果作用范围是其下方的整个屏幕内容,而非当前Stack内部的组件。当列表存在多个item时,每个item的BackdropFilter会模糊下方所有已渲染的列表项(包括其他图片),即便当前item的图片加载完成,模糊层依然会显示下方内容的模糊效果,看起来像是模糊层未被覆盖。
修复方案
方案一:用裁剪组件限制BackdropFilter作用范围
给每个Stack添加ClipRRect或ClipRect包裹,让BackdropFilter仅作用于当前item内部:return ClipRRect( child: Stack( children: [ BackdropFilter( filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: Container( color: Colors.grey, width: double.infinity, height: imageHieght, ), ), CachedNetworkImage( imageUrl: 'https://evrak.co/uploads/images/2022/10/UvpXJ.webp', fit: BoxFit.cover, height: imageHieght, width: double.infinity, ), ], ), );方案二:改用ImageFiltered替代BackdropFilter
若仅需要模糊占位容器,直接用ImageFiltered模糊容器本身,无需作用于背景:return Stack( children: [ ImageFiltered( imageFilter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: Container( color: Colors.grey, width: double.infinity, height: imageHieght, ), ), CachedNetworkImage( imageUrl: 'https://evrak.co/uploads/images/2022/10/UvpXJ.webp', fit: BoxFit.cover, height: imageHieght, width: double.infinity, ), ], );方案三:利用CachedNetworkImage的占位符参数
直接通过CachedNetworkImage自带的placeholder实现加载时的模糊效果,逻辑更清晰:return CachedNetworkImage( imageUrl: 'https://evrak.co/uploads/images/2022/10/UvpXJ.webp', fit: BoxFit.cover, height: imageHieght, width: double.infinity, placeholder: (context, url) => ImageFiltered( imageFilter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: Container(color: Colors.grey), ), );
内容的提问来源于stack exchange,提问作者Yousuf Essa
相关产品推荐
相关产品推荐

