Flutter中添加全局防护水印的实现

随着版权意识的加强,越来越多的应用开始在应用内部增加各种各样的水印信息,防止核心信息泄露,便于朔源。

效果如下:

在Flutter中增加全局水印的方式,目前有两种实现。

方案一,在native层添加一个遮罩层,但这种方式需要双端都要开发,效率低下,维护成本高,优点当然也有,那就是性能高。

方案二:直接在Flutter中添加一个悬浮层实现企微,飞书等界面的水印效果,就如上图中的效果一样。

为了凸显Flutter的高效,当然是直接使用Flutter中的Api进行实现。

第一步:创建所需的水印样式:

dart 复制代码
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);

  @override
  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的特性,动态添加与删除。

dart 复制代码
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,毕竟不是所有界面都需要添加水印。

第三步:在需要的界面增加水印

dart 复制代码
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
  GlobalWaterMarkUtil waterMarkUtil = GlobalWaterMarkUtil();

  @override
  void initState() {
    super.initState();
    addGlobalWatermark();
  }

  ///添加全局水印
  void addGlobalWatermark(){
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      waterMarkUtil.addCustomWatermark(
          context,
          WaterMarkWidget(
            text: 'Hello Flutter \n ${DateTime.now()}',
          ));
    });
  }

  @override
  void dispose() {
    waterMarkUtil.removeWatermark();
    super.dispose();
  }
 }

经过这简单的三步,即可实现全局水印的效果,在使用时,一定要记得在dispose中调用移除函数,不然容易出现水印重叠的效果,如果是针对整个App添加水印,那只需要在Flutter的HomePage里面添加一次即可,因为HomePage永远在栈底,所以水印将一直悬浮在所有页面之上。

相关推荐
小蜜蜂嗡嗡3 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
瓜子三百克6 小时前
十、高级概念
flutter
帅次19 小时前
Objective-C面向对象编程:类、对象、方法详解(保姆级教程)
flutter·macos·ios·objective-c·iphone·swift·safari
小蜜蜂嗡嗡20 小时前
flutter flutter_vlc_player播放视频设置循环播放失效、初始化后获取不到视频宽高
flutter
孤鸿玉1 天前
[Flutter小技巧] Row中widget高度自适应的几种方法
flutter
bawomingtian1231 天前
FlutterView 源码解析
flutter
Zender Han1 天前
Flutter 进阶:实现带圆角的 CircularProgressIndicator
flutter
nc_kai1 天前
Flutter 之 每日翻译 PreferredSizeWidget
java·前端·flutter
littlegnal1 天前
Flutter Add-to-app profiling
flutter