单行:
package cn.shengwang.component.watermark.single;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import cn.shengwang.utils.FcrDpExtKt;
/**
* date : 2024/11/28
* description : 只在对角线上显示一行水印
*/
public class FcrWatermarkSingleDrawableFrm extends Drawable {
private Paint mPaint;
protected String mText;
int mTextColor;
float mTextSize;
float mRotation;
FcrWatermarkSingleDrawableFrm() {
mPaint = new Paint();
}
@Override
public void draw(@NonNull Canvas canvas) {
int width = getBounds().right;
int height = getBounds().bottom;
int diagonal = (int) Math.sqrt(width * width + height * height);
mPaint.setColor(mTextColor);
mPaint.setTextSize(FcrDpExtKt.getDp(mTextSize));
mPaint.setAntiAlias(true);
float textWidth = mPaint.measureText(mText);
// 清空背景
canvas.drawColor(0x00000000);
// 旋转画布到对角线方向
canvas.rotate(mRotation, width / 2f, height / 2f);
// 计算绘制起点
float startX = -diagonal / 2f;
float startY = height / 2f;
// 在对角线上绘制多个水印
//positionX += textWidth * 2 水印间隔
for (float positionX = startX; positionX < diagonal / 2f; positionX += textWidth + (textWidth / 3)) {
canvas.drawText(mText, positionX, startY, mPaint);
}
canvas.save();
canvas.restore();
}
@Override
public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
package cn.shengwang.component.watermark.single;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.fragment.app.Fragment;
/**
*
* date : 2024/11/28
* description : 单行水印显示Fragment
*/
public class FcrWatermarkSingleFrm {
private String mText;
private int mTextColor;
private float mTextSize;
private float mRotation;
private String mTag; //标记
private static FcrWatermarkSingleFrm sInstance;
private FcrWatermarkSingleFrm() {
mText = "";
mTextColor = 0xAEAEAEAE;
mTextSize = 18;
mRotation = -45;
}
public static FcrWatermarkSingleFrm getInstance() {
if (sInstance == null) {
synchronized (FcrWatermarkSingleFrm.class) {
sInstance = new FcrWatermarkSingleFrm();
}
}
return sInstance;
}
public FcrWatermarkSingleFrm setText(String text) {
mText = text;
return sInstance;
}
public FcrWatermarkSingleFrm setTextColor(int color) {
mTextColor = color;
return sInstance;
}
public FcrWatermarkSingleFrm setTextSize(float size) {
mTextSize = size;
return sInstance;
}
public FcrWatermarkSingleFrm setRotation(float degrees) {
mRotation = degrees;
return sInstance;
}
public void show(Fragment fragment, String text, String tag) {
this.mTag = tag;
FcrWatermarkSingleDrawableFrm drawable = new FcrWatermarkSingleDrawableFrm();
drawable.mText = text;
drawable.mTextColor = mTextColor;
drawable.mTextSize = mTextSize;
drawable.mRotation = mRotation;
ViewGroup rootView = (ViewGroup) fragment.getView();
if (rootView != null) {
String watermarkTag = tag;
FrameLayout existingWatermark = rootView.findViewWithTag(watermarkTag);
if (existingWatermark == null) {
FrameLayout layout = new FrameLayout(fragment.getContext());
layout.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
layout.setBackground(drawable);
layout.setTag(watermarkTag);
rootView.addView(layout);
}
}
}
/**
* 移除水印
*
* @param fragment
*/
public void remove(Fragment fragment) {
ViewGroup rootView = (ViewGroup) fragment.getView();
if (rootView != null) {
String watermarkTag = mTag;
FrameLayout existingWatermark = rootView.findViewWithTag(watermarkTag);
if (existingWatermark != null) {
rootView.removeView(existingWatermark);
}
}
}
}
多行
package cn.shengwang.component.watermark.multi;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import cn.shengwang.utils.FcrDpExtKt;
/**
* date : 2024/11/28
* description : 多行显示水印Fragment
*/
public class FcrWatermarkDrawableFrm extends Drawable {
private Paint mPaint;
protected String mText;
int mTextColor;
float mTextSize;
float mRotation;
FcrWatermarkDrawableFrm() {
mPaint = new Paint();
}
@Override
public void draw(@NonNull Canvas canvas) {
int width = getBounds().right;
int height = getBounds().bottom;
int diagonal = (int) Math.sqrt(width * width + height * height);
mPaint.setColor(mTextColor);
mPaint.setTextSize(FcrDpExtKt.getDp(mTextSize));
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;
for (float positionX = fromX; positionX < width; positionX += textWidth * 2) {
canvas.drawText(mText, positionX, positionY, mPaint);
}
}
canvas.save();
canvas.restore();
}
@Override
public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
package cn.shengwang.component.watermark.multi;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.fragment.app.Fragment;
/**
* date : 2024/11/28
* description : 多行显示水印Fragment
*/
public class FcrWatermarkFrm {
private String mText;
private int mTextColor;
private float mTextSize;
private float mRotation;
private String mTag; //标记
private static FcrWatermarkFrm sInstance;
private FcrWatermarkFrm() {
mText = "";
mTextColor = 0xAEAEAEAE;
mTextSize = 18;
mRotation = -25;
}
public static FcrWatermarkFrm getInstance() {
if (sInstance == null) {
synchronized (FcrWatermarkFrm.class) {
sInstance = new FcrWatermarkFrm();
}
}
return sInstance;
}
public FcrWatermarkFrm setText(String text) {
mText = text;
return sInstance;
}
public FcrWatermarkFrm setTextColor(int color) {
mTextColor = color;
return sInstance;
}
public FcrWatermarkFrm setTextSize(float size) {
mTextSize = size;
return sInstance;
}
public FcrWatermarkFrm setRotation(float degrees) {
mRotation = degrees;
return sInstance;
}
public void show(Fragment fragment, String text, String tag) {
this.mTag = tag;
FcrWatermarkDrawableFrm drawable = new FcrWatermarkDrawableFrm();
drawable.mText = text;
drawable.mTextColor = mTextColor;
drawable.mTextSize = mTextSize;
drawable.mRotation = mRotation;
ViewGroup rootView = (ViewGroup) fragment.getView();
if (rootView != null) {
String watermarkTag = tag;
FrameLayout existingWatermark = rootView.findViewWithTag(watermarkTag);
if (existingWatermark == null) {
FrameLayout layout = new FrameLayout(fragment.getContext());
layout.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
layout.setBackground(drawable);
layout.setTag(watermarkTag);
rootView.addView(layout);
}
}
}
/**
* 移除水印
*
* @param fragment
*/
public void remove(Fragment fragment) {
ViewGroup rootView = (ViewGroup) fragment.getView();
if (rootView != null) {
String watermarkTag = mTag;
FrameLayout existingWatermark = rootView.findViewWithTag(watermarkTag);
if (existingWatermark != null) {
rootView.removeView(existingWatermark);
}
}
}
}
activity中用:
package cn.shengwang.component.watermark.multi;
import android.app.Activity;
import android.view.ViewGroup;
import android.widget.FrameLayout;
/**
* date : 2024/11/28
* description :多行显示水印Activity (保留暂不删除目前需求只使用到了Fragment)
*/
public class FcrWatermarkAct {
/**
* 水印文本
*/
private String mText;
/**
* 字体颜色,十六进制形式,例如:0xAEAEAEAE
*/
private int mTextColor;
/**
* 字体大小,单位为sp
*/
private float mTextSize;
/**
* 旋转角度
*/
private float mRotation;
private static FcrWatermarkAct sInstance;
private FcrWatermarkAct() {
mText = "";
mTextColor = 0xAEAEAEAE;
mTextSize = 18;
mRotation = -25;
}
public static FcrWatermarkAct getInstance() {
if (sInstance == null) {
synchronized (FcrWatermarkAct.class) {
sInstance = new FcrWatermarkAct();
}
}
return sInstance;
}
/**
* 设置水印文本
*
* @param text 文本
* @return Watermark实例
*/
public FcrWatermarkAct setText(String text) {
mText = text;
return sInstance;
}
/**
* 设置字体颜色
*
* @param color 颜色,十六进制形式,例如:0xAEAEAEAE
* @return Watermark实例
*/
public FcrWatermarkAct setTextColor(int color) {
mTextColor = color;
return sInstance;
}
/**
* 设置字体大小
*
* @param size 大小,单位为sp
* @return Watermark实例
*/
public FcrWatermarkAct setTextSize(float size) {
mTextSize = size;
return sInstance;
}
/**
* 设置旋转角度
*
* @param degrees 度数
* @return Watermark实例
*/
public FcrWatermarkAct 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) {
FcrWatermarkDrawableAct drawable = new FcrWatermarkDrawableAct();
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);
}
}
package cn.shengwang.component.watermark.multi;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import cn.shengwang.utils.FcrDpExtKt;
/**
* date : 2024/11/28
* description : 多行显示水印Activity(保留暂不删除目前需求只使用到了Fragment)
*/
public class FcrWatermarkDrawableAct extends Drawable {
private Paint mPaint;
/**
* 水印文本
*/
protected String mText;
/**
* 字体颜色,十六进制形式,例如:0xAEAEAEAE
*/
int mTextColor;
/**
* 字体大小,单位为sp
*/
float mTextSize;
/**
* 旋转角度
*/
float mRotation;
FcrWatermarkDrawableAct() {
mPaint = new Paint();
}
@Override
public void draw(@NonNull Canvas canvas) {
int width = getBounds().right;
int height = getBounds().bottom;
int diagonal = (int) Math.sqrt(width * width + height * height); // 对角线的长度
mPaint.setColor(mTextColor);
mPaint.setTextSize(FcrDpExtKt.getDp(mTextSize));
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();
}
@Override
public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
工具类:
package cn.shengwang.component.watermark
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.fragment.app.Fragment
import cn.shengwang.component.watermark.multi.FcrWatermarkFrm
import cn.shengwang.component.watermark.single.FcrWatermarkSingleFrm
/**
* date : 2024/11/28
* description : 统一管理单行和多行水印的显示
*/
object WaterMarkUtils {
const val SINGLE_TYPE = "single_type"
const val MULTI_TYPE = "multi_type"
/**
* @param fragment 容器fragment
* @param content 水印内容
* @param type 是单行还是多行
* @param tag 借助tab 防止多次添加水印以及删除操作 (这个参数不用传默认值就ok 和 remove方法对齐)
*/
fun show(fragment: Fragment, content: String, type: String, tag: String = "mark") {
when (type) {
SINGLE_TYPE -> {
FcrWatermarkSingleFrm.getInstance().show(fragment, content, tag)
}
MULTI_TYPE -> {
FcrWatermarkFrm.getInstance().show(fragment, content, tag)
}
}
}
/**
* 移除水印不区分是单行还是多行
* @param tag 直接使用默认值就ok
*/
fun remove(fragment: Fragment, tag: String = "mark") {
val rootView = fragment.view as ViewGroup?
if (rootView != null) {
val watermarkTag: String = tag
val existingWatermark = rootView.findViewWithTag<FrameLayout>(watermarkTag)
if (existingWatermark != null) {
rootView.removeView(existingWatermark)
}
}
}
}