Flutter三方库适配OpenHarmony【secure_application】— SecureGate 模糊遮罩实现原理
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.netSecureGate 是用户能直接看到的部分——当应用锁定时,一层毛玻璃效果的遮罩覆盖在内容上方,用户什么都看不清。这个效果完全用实现,不依赖任何原生 UI,所以在 OpenHarmony 上天然就能工作。但理解它的实现原理,对于调优模糊效果、自定义锁屏界面都很有帮助。今天我们把 Secu
前言
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
SecureGate 是用户能直接看到的部分——当应用锁定时,一层毛玻璃效果的遮罩覆盖在内容上方,用户什么都看不清。这个效果完全用 Flutter Widget 实现,不依赖任何原生 UI,所以在 OpenHarmony 上天然就能工作。
但理解它的实现原理,对于调优模糊效果、自定义锁屏界面都很有帮助。今天我们把 SecureGate 的每一行代码都讲透。
一、SecureGate 的整体结构
1.1 Widget 定义
class SecureGate extends StatefulWidget {
final Widget child;
final Widget Function(BuildContext context,
SecureApplicationController? secureApplicationController)? lockedBuilder;
final double blurr;
final double opacity;
const SecureGate({
Key? key,
required this.child,
this.blurr = 20,
this.opacity = 0.6,
this.lockedBuilder,
}) : super(key: key);
}
1.2 参数说明
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
child |
Widget | 必填 | 需要保护的内容 |
blurr |
double | 20 | 高斯模糊半径(越大越模糊) |
opacity |
double | 0.6 | 遮罩层透明度(0透明,1不透明) |
lockedBuilder |
Function? | null | 锁定时显示在遮罩上方的自定义 Widget |
1.3 blurr 值与视觉效果
| blurr 值 | 效果 | 适用场景 |
|---|---|---|
| 5 | 轻微模糊,能隐约看到内容 | 非敏感内容 |
| 20 | 中度模糊,基本看不清 | 一般场景(默认值) |
| 60 | 重度模糊,完全看不清 | 金融/医疗等高敏感场景 |
| 100 | 极度模糊,纯色效果 | 最高安全级别 |
💡 实际经验:blurr=20 配合 opacity=0.6 在大多数场景下效果不错。如果内容中有大字号文字,建议提高到 40 以上。
二、Stack + BackdropFilter 布局
2.1 build 方法
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
widget.child,
if (_gateVisibility.value != 0)
Positioned.fill(
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: widget.blurr * _gateVisibility.value,
sigmaY: widget.blurr * _gateVisibility.value),
child: Container(
decoration: BoxDecoration(
color: Colors.grey.shade200
.withOpacity(widget.opacity * _gateVisibility.value)),
),
),
),
if (_lock && widget.lockedBuilder != null)
widget.lockedBuilder!(context, _secureApplicationController),
],
);
}
2.2 三层 Stack 结构
┌─────────────────────────────────┐
│ 第3层:lockedBuilder(解锁按钮) │ ← 只在锁定时显示
├─────────────────────────────────┤
│ 第2层:BackdropFilter(模糊遮罩) │ ← 动画控制显隐
├─────────────────────────────────┤
│ 第1层:child(受保护的内容) │ ← 始终存在
└─────────────────────────────────┘
2.3 BackdropFilter 的工作原理
BackdropFilter 是 Flutter 提供的一个 Widget,它会对其下方的所有内容应用滤镜效果:
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
child: Container(
color: Colors.grey.shade200.withOpacity(0.6),
),
)
| 属性 | 作用 |
|---|---|
sigmaX |
水平方向的模糊半径 |
sigmaY |
垂直方向的模糊半径 |
child |
遮罩层本身的内容(半透明灰色背景) |
📌 注意:BackdropFilter 必须配合
Positioned.fill使用,确保它覆盖整个区域。如果不用Positioned.fill,模糊效果可能只应用到部分区域。
2.4 Positioned.fill 的作用
Positioned.fill(
child: BackdropFilter(...)
)
Positioned.fill 等价于 Positioned(left: 0, right: 0, top: 0, bottom: 0),让 BackdropFilter 填满整个 Stack 区域。
三、AnimationController 动画控制
3.1 动画初始化
class _SecureGateState extends State<SecureGate> with SingleTickerProviderStateMixin {
bool _lock = false;
late AnimationController _gateVisibility;
void initState() {
_gateVisibility = AnimationController(
vsync: this,
duration: kThemeAnimationDuration * 2)
..addListener(_handleChange);
SecureApplicationNative.opacity(widget.opacity);
super.initState();
}
}
3.2 动画参数
| 参数 | 值 | 说明 |
|---|---|---|
vsync |
this | 使用 SingleTickerProviderStateMixin 提供的 Ticker |
duration |
kThemeAnimationDuration * 2 | 约 400ms(200ms × 2) |
value 范围 |
0.0 ~ 1.0 | 0=完全透明,1=完全模糊 |
3.3 锁定与解锁的动画行为
void _sercureNotified() {
if (_lock == false && _secureApplicationController!.locked == true) {
// 锁定:立即显示遮罩
_lock = true;
_gateVisibility.value = 1; // 直接设为1,不做动画
} else if (_lock == true && _secureApplicationController!.locked == false) {
// 解锁:动画淡出遮罩
_lock = false;
_gateVisibility.animateBack(0).orCancel; // 从1渐变到0
}
}
| 操作 | 动画方式 | 原因 |
|---|---|---|
| 锁定 | 立即显示(value=1) | 安全优先,不能让用户看到内容 |
| 解锁 | 渐变消失(animateBack) | 用户体验,平滑过渡 |
💡 设计巧思:锁定时不做动画是有意为之。如果锁定也做渐变动画,在动画过程中用户可能短暂看到敏感内容,这是安全隐患。
3.4 _handleChange 回调
void _handleChange() {
setState(() {
// The listenable's state is our build state, and it changed already.
});
}
每帧动画都触发 setState,让 build 方法重新执行,更新模糊强度。
3.5 动画值与模糊强度的关系
// 模糊强度 = blurr参数 × 动画值
sigmaX: widget.blurr * _gateVisibility.value
// 当 _gateVisibility.value = 0.5 时,模糊强度是 blurr 的一半
// 当 _gateVisibility.value = 1.0 时,模糊强度是 blurr 的全部
解锁时的渐变效果:
时间 0ms: value=1.0 → sigma=20 → 完全模糊
时间 100ms: value=0.75 → sigma=15 → 较模糊
时间 200ms: value=0.5 → sigma=10 → 中等模糊
时间 300ms: value=0.25 → sigma=5 → 轻微模糊
时间 400ms: value=0.0 → sigma=0 → 完全清晰
四、Controller 监听与生命周期
4.1 获取 Controller
SecureApplicationController? _secureApplicationController;
void didChangeDependencies() {
if (_secureApplicationController == null) {
_secureApplicationController = SecureApplicationProvider.of(context);
_secureApplicationController!.addListener(_sercureNotified);
_sercureNotified(); // 立即检查当前状态
}
super.didChangeDependencies();
}
为什么在 didChangeDependencies 而不是 initState 中获取?因为 SecureApplicationProvider.of(context) 需要 BuildContext,而 initState 中的 context 还不完整。
4.2 opacity 同步
void didUpdateWidget(SecureGate oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.opacity != widget.opacity) {
SecureApplicationNative.opacity(widget.opacity);
}
}
当 opacity 参数变化时(比如用户拖动滑块),同步通知原生端。这主要是为了 iOS 平台的原生模糊遮罩。
4.3 资源释放
void dispose() {
_secureApplicationController!.removeListener(_sercureNotified);
_gateVisibility.dispose();
super.dispose();
}
两件事:
- 移除 Controller 的监听器,防止内存泄漏
- 释放 AnimationController
五、lockedBuilder 自定义解锁界面
5.1 基本用法
SecureGate(
blurr: 20,
lockedBuilder: (context, controller) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.lock, size: 64, color: Colors.white),
SizedBox(height: 16),
Text('应用已锁定', style: TextStyle(color: Colors.white, fontSize: 24)),
SizedBox(height: 32),
ElevatedButton(
onPressed: () => controller?.authSuccess(unlock: true),
child: Text('点击解锁'),
),
],
),
),
child: MyProtectedContent(),
)
5.2 集成生物识别
lockedBuilder: (context, controller) => Center(
child: ElevatedButton.icon(
icon: Icon(Icons.fingerprint),
label: Text('指纹解锁'),
onPressed: () async {
final localAuth = LocalAuthentication();
final didAuth = await localAuth.authenticate(
localizedReason: '请验证身份以查看内容',
);
if (didAuth) {
controller?.authSuccess(unlock: true);
} else {
controller?.authFailed();
}
},
),
)
5.3 lockedBuilder 的显示条件
if (_lock && widget.lockedBuilder != null)
widget.lockedBuilder!(context, _secureApplicationController),
两个条件同时满足才显示:
_lock == true:当前处于锁定状态widget.lockedBuilder != null:开发者提供了自定义 Builder
如果没有提供 lockedBuilder,锁定时只显示模糊遮罩,没有解锁按钮。这种情况下解锁需要通过 SecureApplication.onNeedUnlock 回调来处理。
六、blurr 与 opacity 的动态调节
6.1 运行时调节
class _MyAppState extends State<MyApp> {
double _blurr = 20;
double _opacity = 0.6;
Widget build(BuildContext context) {
return SecureGate(
blurr: _blurr,
opacity: _opacity,
child: Column(
children: [
Slider(
value: _blurr,
min: 0, max: 100,
onChanged: (v) => setState(() => _blurr = v),
),
Slider(
value: _opacity,
min: 0, max: 1,
onChanged: (v) => setState(() => _opacity = v),
),
Text('受保护的内容'),
],
),
);
}
}
6.2 不同组合的效果
| blurr | opacity | 效果 |
|---|---|---|
| 0 | 0 | 无遮罩(不安全) |
| 5 | 0.3 | 轻微遮挡 |
| 20 | 0.6 | 标准效果 |
| 60 | 0.8 | 强遮挡 |
| 100 | 1.0 | 完全不透明 |
📌 建议:不要把 blurr 和 opacity 都设为0,那样锁定时用户还是能看到内容,失去了保护的意义。
七、在 OpenHarmony 上的表现
7.1 渲染兼容性
SecureGate 使用的是标准 Flutter Widget:
Stack:布局容器BackdropFilter:高斯模糊AnimationController:动画控制Container+BoxDecoration:背景色
这些都是 Flutter 框架的核心 Widget,在 OpenHarmony 上的 Flutter 渲染引擎中完全支持,不需要任何适配。
7.2 性能考量
BackdropFilter 的高斯模糊是 GPU 加速的,在 OpenHarmony 设备上的性能表现:
| 设备类型 | blurr=20 | blurr=60 | blurr=100 |
|---|---|---|---|
| 高端手机 | 流畅 | 流畅 | 流畅 |
| 中端手机 | 流畅 | 轻微掉帧 | 可能掉帧 |
| 低端设备 | 流畅 | 可能掉帧 | 建议降低 |
7.3 与原生隐私模式的配合
SecureGate 的模糊遮罩和原生端的 setWindowPrivacyMode 是互补关系:
| 层级 | 机制 | 保护范围 |
|---|---|---|
| Flutter 层 | BackdropFilter 模糊遮罩 | 用户回到 App 时看到的内容 |
| 原生层 | setWindowPrivacyMode | 应用切换器中的缩略图、截屏 |
两者缺一不可:
- 只有 Flutter 层遮罩:应用切换器中还是能看到内容
- 只有原生层隐私模式:用户回到 App 时能直接看到内容
总结
本文详细分析了 SecureGate 模糊遮罩的实现原理:
- 三层 Stack 结构:child + BackdropFilter + lockedBuilder
- BackdropFilter:GPU 加速的高斯模糊,sigmaX/sigmaY 控制模糊强度
- AnimationController:锁定立即显示,解锁渐变消失
- lockedBuilder:支持自定义解锁界面,可集成生物识别
- 跨平台兼容:纯 Flutter Widget 实现,OpenHarmony 上无需适配
下一篇我们分析 Android 端的 FLAG_SECURE 实现——理解它有助于我们在 OpenHarmony 上找到对应的方案。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- Flutter BackdropFilter 文档
- Flutter AnimationController 文档
- ImageFilter.blur 文档
- SingleTickerProviderStateMixin
- local_auth 生物识别插件
- secure_application 源码
- Flutter 动画指南
- 开源鸿蒙跨平台社区

SecureGate 锁定状态下的高斯模糊遮罩效果
更多推荐

所有评论(0)