页面中满屏水印

2023-11-04

1. 前言

现在市面上,有很多APP在一些关键页面上会有水印,水印一般都是一些身份相关的信息,这样可以保证截屏后的图片具有识别性,能够知道这张截图是谁截取的。

2. 具体实现

为了能够方便地在任意页面上加水印,所以应该采取用Java代码来实现,而不是在XML布局文件里面写。大概思路是,首先获取当前页面的底层布局,然后在布局最上层添加一个全屏的带有水印的FrameLayout布局。这个全屏的带有水印的FrameLayout布局,我们可以在XML写。很多博客文章都是介绍这种方式来写水印,不过大多数都没做适配,特别是横屏显示时,水印效果很不好。所以我这里用Java代码来画水印。自定义一个Drawable,把它当作水印,然后设置到FrameLayout布局的背景,这样就行了。相关代码如下所示:

import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;

import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.annotation.Nullable;

public class Watermark {
    /*** 水印文本*/
    private String mText;
    /*** 字体颜色,十六进制形式,例如:0xAEAEAEAE*/
    private int mTextColor;
    /*** 字体大小,单位为sp*/
    private float mTextSize;
    /*** 旋转角度*/
    private float mRotation;
    private static Watermark sInstance;

    private Watermark() {
        mText = "";
        mTextColor = 0xAEAEAEAE;
        mTextSize = 18;
        mRotation = -25;
    }

    public static Watermark getInstance() {
        if (sInstance == null) {
            synchronized (Watermark.class) {
                sInstance = new Watermark();
            }
        }
        return sInstance;
    }

    /*** 设置水印文本** @param text 文本* @return Watermark实例*/
    public Watermark setText(String text) {
        mText = text;
        return sInstance;
    }

    /*** 设置字体颜色** @param color 颜色,十六进制形式,例如:0xAEAEAEAE* @return Watermark实例*/
    public Watermark setTextColor(int color) {
        mTextColor = color;
        return sInstance;
    }

    /*** 设置字体大小** @param size 大小,单位为sp* @return Watermark实例*/
    public Watermark setTextSize(float size) {
        mTextSize = size;
        return sInstance;
    }

    /*** 设置旋转角度** @param degrees 度数* @return Watermark实例*/
    public Watermark setRotation(float degrees) {
        mRotation = degrees;
        return sInstance;
    }

    /*** 显示水印,铺满整个页面** @param activity 活动*/
    public void show(Activity activity) {
        show(activity, mText);
    }

    /*** 显示水印,铺满整个页面** @param activity 活动* @param text     水印*/
    public void show(Activity activity, String text) {
        WatermarkDrawable drawable = new WatermarkDrawable();
        drawable.mText = text;
        drawable.mTextColor = mTextColor;
        drawable.mTextSize = mTextSize;
        drawable.mRotation = mRotation;
        ViewGroup rootView = activity.findViewById(android.R.id.content);
        FrameLayout layout = new FrameLayout(activity);
        layout.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        layout.setBackground(drawable);
        rootView.addView(layout);
    }


    class WatermarkDrawable extends Drawable {
        private Paint mPaint;
        /*** 水印文本*/
        private String mText;
        /*** 字体颜色,十六进制形式,例如:0xAEAEAEAE*/
        private int mTextColor;
        /*** 字体大小,单位为sp*/
        private float mTextSize;
        /*** 旋转角度*/
        private float mRotation;

        WatermarkDrawable() {
            mPaint = new Paint();
        }

        @Override
        public void draw(Canvas canvas) {
            int width = getBounds().right;
            int height = getBounds().bottom;
            int diagonal = (int) Math.sqrt(width * width + height * height); // 对角线的长度mPaint.setColor(mTextColor);mPaint.setTextSize(ConvertUtils.spToPx(mTextSize)); // ConvertUtils.spToPx()这个方法是将sp转换成px,ConvertUtils这个工具类在我提供的demo里面有mPaint.setAntiAlias(true);float textWidth = mPaint.measureText(mText);canvas.drawColor(0x00000000);canvas.rotate(mRotation);int index = 0;float fromX;// 以对角线的长度来做高度,这样可以保证竖屏和横屏整个屏幕都能布满水印for (int positionY = diagonal / 10; positionY <= diagonal; positionY += diagonal / 10) {fromX = -width + (index++ % 2) * textWidth; // 上下两行的X轴起始点不一样,错开显示for (float positionX = fromX; positionX < width; positionX += textWidth * 2) {canvas.drawText(mText, positionX, positionY, mPaint);}}canvas.save();canvas.restore();}@Overridepublic void setAlpha(@IntRange(from = 0, to = 255) int alpha) {}@Overridepublic void setColorFilter(@Nullable ColorFilter colorFilter) {}@Overridepublic int getOpacity() {return PixelFormat.TRANSLUCENT;}}
        }

        @Override
        public void setAlpha(int alpha) {

        }

        @Override
        public void setColorFilter(@Nullable ColorFilter colorFilter) {

        }

        @Override
        public int getOpacity() {
            return PixelFormat.UNKNOWN;
        }
    }

}

3. 使用方式

为了保证能够在当前页面的最顶层加水印,应该在 setContentView() 后面添加水印

@Overrideprotected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Watermark.getInstance().show(this, "Fantasy BlogDemo");// 可以自定义水印文字颜色、大小和旋转角度
    Watermark.getInstance().setText("Fantasy BlogDemo").setTextColor(0xAE000000)        .setTextSize(16).setRotation(-30).show(this);}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

页面中满屏水印 的相关文章

  • vue-video-player基本使用

    下载 npm install vue video player 如果不使用vue的话 可以直接去官网 或者cdn获取对应js即可 在vue中的基本使用 main js中 全局 import Vue from vue import VueVi
  • 线程与进程的对比、互斥锁和条件变量的使用-多线程编程

    线程与进程的对比 线程的概念是共享CPU的需要 进程概念是共享内存的需要 一个进程里代码段 数据段 堆是共享的 但是进程中的每个线程中的栈 寄存器内容独立 进程都是独立的 通常的IPC 管道 共享内存都可以通讯 处于一个线程的代码觉得它拥有
  • Redis基础知识(二):事务机制

    文章目录 一 什么是事务机制 二 Redis模式下如何实现事务机制 2 1 显式开启一个事务 2 2 将命令入队列Queue 2 3 执行事务或丢弃 2 4 EXEC命令执行示例 2 5 DISCARD命令 放弃事务 2 6 因为命令错误导
  • RabbitMQ用途及问题

    转自 https blog csdn net u013871100 column info 27053 1 用途 1 解耦 系统A在代码中直接调用系统B和系统C的代码 如果将来D系统接入 系统A还需要修改代码 过于麻烦 2 异步 将消息写入
  • ROS学习笔记(五)---话题发布

    1 话题通信是什么 在ROS 机器人操作系统 中 话题通信是一种常用的通信机制 用于在不同的ROS节点之间传递消息 话题通信基于发布者 订阅者模式 其中一个节点 发布者 发布消息到一个特定的话题 而其他节点 订阅者 可以订阅该话题以接收消息
  • 一篇文章让你深入了解RGB数据格式和互转(YUV数据组成)

    我们日常看到的图片 视频由RGB或YUV数据组成 说明 1 RGB分为RGB16 RGB24 RGB32 RGB RGB16 RGB24 RGB32 一 RGB分RGB16 RGB24 RGB32 1 RGB16格式分为RGB565 RGB
  • 某市财政收入预测分析:GM模型+神经网络

    from numpy random import seed seed 1 import tensorflow tensorflow random set seed 2 import numpy as np import pandas as
  • openssl生成椭圆曲线的私钥是如何做到每次不同的?

    目录 例子 排查 随机算法 小结 例子 生成一个私钥只需要3步 1 获得指定曲线的group 如比特币的secp256k1 2 group和key绑定 3 用key来生成私钥 先上一段代码例子 key1 EC KEY new if key1
  • 2021.11.9

    把数据结构 第一章的课后写了一下 有点难哎 第二章的1 12题 对空间复杂度有了进一步的了解 假设法和最深层语句执行次数 但是涉及到 log 什么的我就不咋会了 如何去设计一个抽象数据类型 基本能将算法的功能看出来 如何设置更加高效的算法
  • 一个完整的语法分析、词法分析例子——Universal Pasrser

    需求 用户用formal notation指定语法 词法 然后可以匹配相应的文本 用法类似正则表达式 只需给出formal notation 不需要为每一种格式的文本单独写匹配器 formal notation主要是3个部分 1 BNF 列
  • 应用层---HTTP协议

    应用层 应用层是TCP IP协议分层的最顶层模型 它的作用是维持好应用程序之间的沟通 维护好特定的协议 如简单电子邮件传输 SMTP 文件传输协议 FTP 网络远程访问协议 Telnet 等 应用层协议分为两种 一种是根据客户要求自己对数据
  • 【计算机网络】章节思维导图《谢希仁第八版》

    仅作为笔记 如有错误 还请斧正 第一章 概述思维导图 第二章 物理层
  • Linux下一种运行时切换动态库的方法

    概述 假设有这样一种应用场景 有一个 lib libfoo so动态库 有两个或多个厂家各自实现了自己的版本 每个版本都不是尽善尽美 分别有自己的优势和缺点 可能app1使用v1版本的库比较合适 app2使用v2版本的库不会出bug等等 在

随机推荐

  • 中国图书分类法检索计算机方面的图书,《中国图书分类法》(简称《中图法》)是我国常用的分类法,要检索计算机方面的图书,需要在( )类目下查找。...

    A Q类目 B T 类目 C S类目 D 答案 中国图书分类法 简称 中图法 是我国常用的分类法 要检索计算机方面的图书 需要在 类目下查找 解析 判断题 查全率是指检索出的符合课题需要的文献与检索出的相关文献量之比 判断题 文献是记录知识
  • SQL基础语句

    SQL SQL简介 SQL Structured Query Language 结构化查询语言 是用于管理关系数据库管理系统 RDBMS SQL 的范围包括数据插入 查询 更新和删除 数据库模式创建和修改 以及数据访问控制 SQL语法 us
  • Java中BigDecimal比较大小的方法

    场景 数据中某字段 是decimal类型 现在要在业务代码中获取某个Model的此属性是否为0 即要将其与0 00比较大小 实现 java中对bigdimical比较大小一般用的是bigdemical的compareTo方法 int a b
  • python进阶-你是否真的懂函数,装饰器,闭包,一等对象

    函数的定义 函数是一段具有特定功能的 可重用的语句组 通过函数名来表示和调用 经过定义 一组语句等价于一个函数 在需要使用这组语句的地方 直接调用函数名称即可 函数的使用包括两部分 函数的定义和函数的使用 以上是函数的通用定义 无可厚非 那
  • [QT_009]Qt学习之QTableWidget详解

    本文转自 Qt编程指南 作者 奇先生 Qt编程指南 Qt新手教程 Qt Programming Guide 8 2 1 QTableWidget 在 Qt 设计师可以拖动表格控件到界面窗口 下图可以直观看到表格控件的大致组成 表格控件最上面
  • python数据分析pandas基础用法

    import pandas as pd df pd read csv cancer data csv df head 返回 dataframe 维度的元组 df shape 返回列的数据类型 df dtypes 虽然供诊断的数据类型是对象
  • Python编写游戏——拼图游戏

    Python编写游戏需要用到pgzrun模块 但不能用pip install pgzrun进行安装 正确的库名是pgzero pip install pgzero 一 开发工具 Python版本 Python 3 6 4或以上版本 二 相关
  • FDTD solution——材料拟合、光源设置

    材料拟合 蓝色线条是FDT的拟合线条 绿色点是试验数据 Material中可以选择拟合的材料 其中包括你添加的材料 fit Tolerance 拟合系数 表示拟合的误差 max coefficients多系数材料模型中 可以用到的最大系数
  • 操作系统学习(五)虚拟内存

    一 定义 在传统存储管理方式的基础上引入了交换技术 覆盖技术 使得内存利用率有所提升 并能从逻辑上扩充内存容量 二 传统存储管理方式的特征 缺点 缺点 一次性 作业必须一次性全部装入内存后 才能开始运行 驻留性 一旦作业被装入内存 就会一直
  • 微信小程序:去水印工具微信小程序源码

    这是一个去水印小程序 支持各大平台短视频去水印 支持图集去水印 另外还有一个功能也就相当于抖音一样刷短视频 偷偷告诉你们哟 刷的短视频都是热门小姐姐哟 惊不惊喜意不意外 小程序源码下载地址 微信小程序 去水印工具微信小程序源码 小程序文档类
  • python的save的用法_MongoDB中如何使用Save()方法更新文档?

    在MongoDB中 可以对操作的文档进行操作 例如如何在数据库中存在了该内容 这部分内容是多余的 那么使用save 方法会执行更新操作 更改原来的内容为新内容 本文介绍MongoDB中使用Save 方法更新文档的相关介绍 1 save 方法
  • VLC控件——属性和方法 .

    VLC调研 VLC控件支持的参数和方法 VLC对象列表 Vlc Plugin Object的方法 l VersionInfo 成员 返回版本信息的字符串 l vlc versionInfo 方法 返回版本信息的字符串 Audio objec
  • 【Java学习日志】2.Spring框架

    Spring管理项目中的类 方法等 Spring 的核心技术 ioc aop 能实现模块之间 类之间的解耦合 举例来说 classA依赖classB spring被用来解决A类和B类之间的关系 Spring boot 2017年出现的框架
  • C语言波形实现三角波和正弦波

    方波 方波波形类似高低电平 所以设置合适的延时时间和高低电平值即可实现方波 正弦波 include math h define PI 3 141592653 float WaveMin 1 0f 波形最小峰值 float WaveMax 5
  • mysql 两个数相加_mysql查询将两列数值相加问题

    如图所示 我希望加一个total price列 值为price price2的和 这个应该怎么写SQL select from ims goods 1 where price 0 and price2 0 奉上SQL文件 Navicat M
  • 外部类可以访问内部类私有属性。

    内部类就相当于一个外部类的成员变量 所以可以直接访问外部变量 外部类不能直接访问内部类变量 必须通过创建内部类实例的方法访问 你想不通的肯定是指内部类的私有变量怎么可以被外部类访问吧 按常规 私有变量m只能在InnerClass里被访问 但
  • 内存泄漏的原因及解决方法

    内存泄漏就是内存中的变量没有回收 一直存在与内存中 造成内存的浪费的行为 常见的内存泄漏有以下5种 1 意外的全局变量 2 计时器和回调函数timers 3 DOM泄漏 4 js闭包 5 console
  • google浏览器扩展翻译程序

    知乎上找的一篇文档 非常好使 https zhuanlan zhihu com p 95634262 google翻译神器
  • python ssh登录incompatible_Paramiko不兼容的SSH服务器(没有可接受的mac)

    我使用paramiko已经有一段时间了 一切正常 但是当我离开测试环境时 在打开ssh会话时出现了这个错误paramiko ssh exception SSHException Incompatible ssh server no acce
  • 页面中满屏水印

    1 前言 现在市面上 有很多APP在一些关键页面上会有水印 水印一般都是一些身份相关的信息 这样可以保证截屏后的图片具有识别性 能够知道这张截图是谁截取的 2 具体实现 为了能够方便地在任意页面上加水印 所以应该采取用Java代码来实现 而