Flutter中如何在组件上方实现反向遮罩效果?
在Flutter中实现反向遮罩效果(图标/文本透明显示背后内容)
我编写了如下的RawMaterialButton组件:
RawMaterialButton( onPressed: () {}, fillColor: Colors.white, padding: const EdgeInsets.all(15), shape: const CircleBorder(), child: Icon( Icons.chevron_right, size: 35, color: context.primaryColor, ), )
它在页面中的显示效果如下:
但页面背景是动态变化的渐变动画,因此右侧的chevron图标颜色也需要随背景变化。我设想将该图标作为反向遮罩,使其透明并显示父组件背后的内容。此外,我还需要实现类似设计:在容器中放置文本,让文本透明并显示父容器的背景。
请问在Flutter中是否有直接可行的实现方式?
提前感谢!
环境信息
Flutter doctor检测结果:
[✓] Flutter (Channel stable, 3.7.0, on Fedora Linux 36 (KDE Plasma) 6.1.8-100.fc36.x86_64, locale en_US.UTF-8) • Flutter version 3.7.0 on channel stable at /home/erayerdin/.local/lib/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision b06b8b2710 (11 days ago), 2023-01-23 16:55:55 -0800 • Engine revision b24591ed32 • Dart version 2.19.0 • DevTools version 2.20.1 [✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0) • Android SDK at /home/erayerdin/.sdks/android/ • Platform android-33, build-tools 33.0.0 • ANDROID_SDK_ROOT = /home/erayerdin/.sdks/android • Java binary at: /var/lib/snapd/snap/android-studio/125/android-studio/jre/bin/java • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866) • All Android licenses accepted. [✓] Chrome - develop for the web • Chrome at google-chrome [✓] Linux toolchain - develop for Linux desktop • clang version 14.0.5 (Fedora 14.0.5-2.fc36) • cmake version 3.25.2 • ninja version 1.10.2 • pkg-config version 1.8.0 [✓] Android Studio (version 2021.3) • Android Studio at /var/lib/snapd/snap/android-studio/125/android-studio • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866) [✓] VS Code • VS Code at /snap/code/current • Flutter extension version 3.58.0 [✓] Connected device (3 available) • sdk gphone64 x86 64 (mobile) • emulator-5554 • android-x64 • Android 13 (API 33) (emulator) • Linux (desktop) • linux • linux-x64 • Fedora Linux 36 (KDE Plasma) 6.1.8-100.fc36.x86_64 • Chrome (web) • chrome • web-javascript • Google Chrome 109.0.5414.119 [✓] HTTP Host Availability • All required HTTP hosts are available • No issues found!
解决方案
Flutter中可以通过BlendMode结合组件嵌套实现反向遮罩效果,以下是两种直接可行的实现方式:
1. 图标反向遮罩实现
利用ShaderMask和BlendMode.dstOut混合模式,让图标区域透明显示背后的动态背景:
Stack( alignment: Alignment.center, children: [ // 示例动态渐变背景 AnimatedContainer( duration: const Duration(seconds: 2), decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.blue, Colors.purple], begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), ), RawMaterialButton( onPressed: () {}, fillColor: Colors.white, padding: const EdgeInsets.all(15), shape: const CircleBorder(), child: ShaderMask( blendMode: BlendMode.dstOut, shaderCallback: (Rect bounds) { return LinearGradient(colors: [Colors.white]).createShader(bounds); }, child: Icon( Icons.chevron_right, size: 35, color: Colors.black, // 颜色仅需不透明,不影响最终效果 ), ), ), ], )
2. 文本反向遮罩实现
通过Stack+ColorFiltered组合,让文本区域挖空显示容器背景:
Stack( alignment: Alignment.center, children: [ // 容器背景(示例渐变) Container( width: 200, height: 100, decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.orange, Colors.red], ), ), ), ColorFiltered( colorFilter: ColorFilter.mode(Colors.white, BlendMode.dstOut), child: Container( width: 200, height: 100, color: Colors.white, child: Center( child: Text( "反向遮罩文本", style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.black, // 颜色仅需不透明,不影响最终效果 ), ), ), ), ), ], )
核心原理
BlendMode.dstOut:会将遮罩区域内的像素转为透明,从而透出下方的背景内容- 遮罩层的图标/文本只需保证不透明,具体颜色不影响最终显示效果
内容的提问来源于stack exchange,提问作者Eray Erdin
相关产品推荐
相关产品推荐

