随着版权意识的加强,越来越多的应用开始在应用内部增加各种各样的水印信息,防止核心信息泄露,便于朔源。
效果如下:
在Flutter中增加全局水印的方式,目前有两种实现。
方案一,在native层添加一个遮罩层,但这种方式需要双端都要开发,效率低下,维护成本高,优点当然也有,那就是性能高。
方案二:直接在Flutter中添加一个悬浮层实现企微,飞书等界面的水印效果,就如上图中的效果一样。
为了凸显Flutter的高效,当然是直接使用Flutter中的Api进行实现。
第一步:创建所需的水印样式:
import 'dart:math';
import 'package:flutter/material.dart';
class WaterMarkWidget extends StatelessWidget {
final int rowCount;//控制每一行显示的水印个数
final int columnCount;//控制每一列显示的个数
final String text;//水印文案
const WaterMarkWidget({
Key? key,
this.rowCount = 2,
this.columnCount = 3,
required this.text,
}) : super(key: key);
Widget build(BuildContext context) {
return IgnorePointer(//这个很关键,一定要忽略焦点事件
child: SafeArea(
child: Padding(
padding: const EdgeInsets.only(top: 50),
child: Column(
children: createColumnWidgets(),
),
),
),
);
}
List<Widget> createRowWidgets() {
List<Widget> list = [];
for (var i = 0; i < rowCount; i++) {
final widget = Expanded(
child: Center(
child: Transform.rotate(
angle: -pi / 4.5,
child: Opacity(
opacity: 0.2,
child: Text(
text,
style: const TextStyle(
fontSize: 12,
color: Colors.blue,
),
),
),
),
),
);
list.add(widget);
}
return list;
}
List<Widget> createColumnWidgets() {
List<Widget> list = [];
for (var i = 0; i < columnCount; i++) {
final widget = Expanded(
child: Row(
children: createRowWidgets(),
));
list.add(widget);
}
return list;
}
}
在这段代码中,核心要注意的是,增加焦点忽略,不然就会出现焦点抢占的问题。
第二步:创建一个水印管理工具类
主要使用了OverlayEntry的特性,动态添加与删除。
import 'package:flutter/material.dart';
class GlobalWaterMarkUtil {
static final GlobalWaterMarkUtil _singleton = GlobalWaterMarkUtil._internal();
factory GlobalWaterMarkUtil() {
return _singleton;
}
GlobalWaterMarkUtil._internal();
OverlayEntry? _overlayEntry;
/// 添加自定义水印。将[widget]覆盖在所有视图的最上层
void addCustomWatermark(BuildContext context, Widget widget) {
_overlayEntry?.remove();
OverlayState? overlayState = Overlay.of(context);
_overlayEntry = OverlayEntry(builder: (context) => widget);
overlayState.insert(_overlayEntry!);
}
/// 移除水印
Future<void> removeWatermark() async {
if (_overlayEntry != null) {
_overlayEntry?.remove();
_overlayEntry = null;
}
}
}
工具类内容简单,主要用于添加和删除OverlayEntry,毕竟不是所有界面都需要添加水印。
第三步:在需要的界面增加水印
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
GlobalWaterMarkUtil waterMarkUtil = GlobalWaterMarkUtil();
void initState() {
super.initState();
addGlobalWatermark();
}
///添加全局水印
void addGlobalWatermark(){
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
waterMarkUtil.addCustomWatermark(
context,
WaterMarkWidget(
text: 'Hello Flutter \n ${DateTime.now()}',
));
});
}
void dispose() {
waterMarkUtil.removeWatermark();
super.dispose();
}
}
经过这简单的三步,即可实现全局水印的效果,在使用时,一定要记得在dispose中调用移除函数,不然容易出现水印重叠的效果,如果是针对整个App添加水印,那只需要在Flutter的HomePage里面添加一次即可,因为HomePage永远在栈底,所以水印将一直悬浮在所有页面之上。