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

news2025/1/5 13:22:15

随着版权意识的加强,越来越多的应用开始在应用内部增加各种各样的水印信息,防止核心信息泄露,便于朔源。
效果如下:
在这里插入图片描述

在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永远在栈底,所以水印将一直悬浮在所有页面之上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2268448.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MQTT——客户端安装使用(图文详解)

目录 一. 下载安装MQTT 1. 下载MQTT 2. 安装MQTT 二. MQTT客户端使用 1. 连接MQTT服务 2. MQTT发布消息 3. MQTT 消息订阅 4. 断开MQTT服务器连接 三. 使用Jmeter给MQTT发数据 一. 下载安装MQTT 1. 下载MQTT &#xff08;1&#xff09;官网下载地址&#xff1a;MQTTX…

2- 位段式结构体

文章目录 1 结构体内存对齐2 位段式结构体2.1 格式2.2 成员类型2.3 空间开辟2.4 示例2.4.1 示例12.4.2 示例2 1 结构体内存对齐 首成员对齐规则 结构体的第一个成员从偏移量为0的地址处开始存放&#xff0c;即与结构体的首地址对齐。 其他成员对齐规则 其他成员变量的存放地址…

Milvus×EasyAi:如何用java从零搭建人脸识别应用

如何从零搭建一个人脸识别应用&#xff1f;不妨试试原生Java人工智能算法&#xff1a;EasyAi Milvus 的组合拳。 本文将使用到的软件和工具包括&#xff1a; EasyAi&#xff1a;人脸特征向量提取Milvus&#xff1a;向量数据库用于高效存储和检索数据。 01. EasyAi&#xff1a;…

AWS K8s 部署架构

Amazon Web Services&#xff08;AWS&#xff09;提供了一种简化的Kubernetes&#xff08;K8s&#xff09;部署架构&#xff0c;使得在云环境中管理和扩展容器化应用变得更加容易。这个架构的核心是AWS EKS&#xff08;Elastic Kubernetes Service&#xff09;&#xff0c;它是…

[Pro Git#2] 分支管理 | branch fix_bug , feature | 处理合并冲突

目录 一、Issue模板文件 二、Pull Requests模板文件 分支管理 1. 理解分支 2. 创建与管理分支 1. 切换分支与提交历史 2. 合并分支 3. 删除分支 4. 解决合并冲突 6. 查看分支合并情况 快速创建并切换分支 分支管理策略 分支合并模式 分支管理原则 日常开发环境 …

Acwing 基础算法课 数学知识 筛法求欧拉函数

【G09 筛法求欧拉函数】https://www.bilibili.com/video/BV1VP411p7Bs?vd_source57dbd16b8c7c2ad258cccce5966c5be8 闫总真是把听者当数学系转cs的来讲&#xff0c;菜逼完全听不懂&#xff0c;只能其他地再搜 欧拉函数 φ ( n ) \varphi(n) φ(n)&#xff1a;1~n中与n互质的数…

SpringCloudAlibaba技术栈-Higress

1、什么是Higress? 云原生网关&#xff0c;干啥的&#xff1f;用通俗易懂的话来说&#xff0c;微服务架构下Higress 就像是一个智能的“交通警察”&#xff0c;它站在你的网络世界里&#xff0c;负责指挥和调度所有进出的“车辆”&#xff08;也就是数据流量&#xff09;。它的…

# 光速上手 - JPA 原生 sql DTO 投影

前言 使用 JPA 时&#xff0c;我们一般通过 Entity 进行实体类映射&#xff0c;从数据库中查询出对象。然而&#xff0c;在实际开发中&#xff0c;有时需要自定义查询结果并将其直接映射到 DTO&#xff0c;而不是实体类。这种需求可以通过 JPA 原生 SQL 查询和 DTO 投影 来实现…

智能故障诊断和寿命预测期刊推荐

往期精彩内容&#xff1a; Python-凯斯西储大学&#xff08;CWRU&#xff09;轴承数据解读与分类处理 基于FFT CNN - BiGRU-Attention 时域、频域特征注意力融合的轴承故障识别模型-CSDN博客 基于FFT CNN - Transformer 时域、频域特征融合的轴承故障识别模型-CSDN博客 P…

MTK抓log方法log机制以及如何抓取log

目录 离线log抓取&#xff1a; adb命令打开mtklog的方法 &#xff1a; 实时log抓取&#xff1a; 设置log等级和打开平台log: 实时抓取&#xff0c;两种方式&#xff1a; Kernel Log: LOG 优先级 logcat 离线log抓取&#xff1a; 1.手机先进入开发者模式 2.进入拨号页面…

人工智能与云计算的结合:如何释放数据的无限潜力?

引言&#xff1a;数据时代的契机 在当今数字化社会&#xff0c;数据已成为推动经济与技术发展的核心资源&#xff0c;被誉为“21世纪的石油”。从个人消费行为到企业运营决策&#xff0c;再到城市管理与国家治理&#xff0c;每个环节都在生成和积累海量数据。然而&#xff0c;数…

如何在 Ubuntu 22.04 上安装 Varnish HTTP 教程

简介 在本教程中&#xff0c;我们将学习如何在 Ubuntu 22.04 服务器上安装和配置 Varnish HTTP。 Varnish 是一款高性能的 HTTP 加速器&#xff0c;旨在提高内容密集型动态网站的速度。它通过将网页缓存在内存中来工作&#xff0c;从而减少 Web 服务器的负载&#xff0c;并显…

AI辅助编码提高病案首页主要诊断编码正确率数据优化方法(2025增量优化版附python源代码)

一、引言 1.1 研究背景与意义 在医疗信息化进程中,病案首页作为病历信息的核心浓缩,承载着疾病分类、医疗统计、医保结算等关键任务,其主要诊断编码的准确性至关重要。准确的编码不仅是医疗质量评估、科研数据分析的基石,更是合理分配医疗资源、保障医保精准支付的关键依…

CSES-1135 Distance Queries

题目传送门https://vjudge.net/problem/CSES-1135#authorGPT_zh 解题思路 题目让我们求树上两个点的距离。 那么就可以转化为两点到其 LCA 的距离之和。 代码 #include<bits/stdc.h> using namespace std;int n,q; vector<int> g[200001]; int dis[200001],dep…

「Mac畅玩鸿蒙与硬件49」UI互动应用篇26 - 数字填色游戏

本篇教程将带你实现一个数字填色小游戏&#xff0c;通过简单的交互逻辑&#xff0c;学习如何使用鸿蒙开发组件创建趣味性强的应用。 关键词 UI互动应用数字填色动态交互逻辑判断游戏开发 一、功能说明 数字填色小游戏包含以下功能&#xff1a; 数字选择&#xff1a;用户点击…

001__VMware软件和ubuntu系统安装(镜像)

[ 基本难度系数 ]:★☆☆☆☆ 一、Vmware软件和Ubuntu系统说明&#xff1a; a、Vmware软件的说明&#xff1a; 官网&#xff1a; 历史版本&#xff1a; 如何下载&#xff1f; b、Ubuntu系统的说明&#xff1a; 4、linux系统的其他版本&#xff1a;红旗(redhat)、dibian、cent…

【NebulaGraph】变化的多跳查询

【NebulaGraph】变化的多跳查询 1. 需求2. 解决方案2.1 确定查询结构2.2 构建查询语句 3. 追加需求&#xff1a;如果增加每一跳都要指定查询某SPACE下的Tag&#xff0c;或者不查询某个Tag怎么办 1. 需求 存在多跳请求&#xff0c;其中每一跳是从上一跳查询结果为基础的。但是 …

【Compose multiplatform教程06】用IDEA编译Compose Multiplatform常见问题

当我们从Kotlin Multiplatform Wizard | JetBrains 下载ComposeMultiplatform项目时 会遇到无法正常编译/运行的情况&#xff0c;一般网页和桌面是可以正常编译的&#xff0c; 我这里着重解决如下问题 1:Gradle版本不兼容或者Gradle连接超时 2:JDK版本不兼容 3:Gradle依赖库连…

如何利用无线路由器实现水泵房远程监测管理

水泵站广泛部署应用在工农业用水、防洪、排涝和抗旱减灾等方面&#xff0c;如果水泵站发生异常&#xff0c;往往会对生产生活造成诸多损失&#xff0c;甚至引发安全事故。因此&#xff0c;建立一套高效、可靠的泵站远程监测管理系统至关重要。 方案背景 目前&#xff0c;我国大…

vue3学习笔记(9)-pinia、storeToRefs、getters

1.新的集中式状态&#xff08;数据&#xff09;管理库&#xff0c;redux vuex pinia 搭建 2.ref拆包 如果在reactive里面定义ref&#xff0c;则打印c时&#xff0c;无需.value 他自动拆包&#xff0c;如果直接在外面定义的ref则需要.value,他没有拆包 3.pinia存储读取数据 存…