- 前言
之前有一篇写过仿钉钉水印的仿钉钉通讯录水印
,不过仔细看了一下,还是略有区别,那一篇改版过很多次了,这里再模仿的更像一些,不过由于之前的实现方式是通过绘制路径然后在路径上绘制文字,但是如果要绘制四条路径的话需要就更麻烦了,害怕以后回过头在看会比较难看懂,这边改成旋转和平移画布的方式绘制倾斜的四段文字。
- 实现思路
做一个东西首先有思路,才能走下去。
仔细观察后发现钉钉中的水印,呈现四段文字一块,重复平铺的。
ok!首先我们将一块展示四段文字水印的图片绘制出来。
四段文字是两个文字重复的,一个是根据姓名和手机号拼接的,一个是默认的一段文字。
一个就叫 namePhoneText,一个就叫它 appName 吧
这个图片分为四个区域
namePhoneText appName
appName namePhoneText
大概就是按照这种位置展示文字的。
然后文字绘制的时候,通过canvas中的平移和旋转方法,调整到指定位置,然后直接绘制,就不使用之前的方案绘制文字路径的方式了,因为要去计算很多起点和终点的位置,这样后期看代码的时候,会很困难。
将文字绘制完成之后,利用BitmapDrawable 类中的setTileModeXY 设置REPEAT重复平铺展示图,设置到需要设置的view的背景上。
更细节的直接看代码,上也写了不少注释了。
@Inject
public WaterMarkTextUtil() {
}
/**
* 字的大小 单位sp
*/
final int textSize = 14;
/**
* 一个字所占的像素
*/
int oneTextPx;
/**
* 当前字符串所占的长度
*/
int textLength;
/**
* 默认后缀文字
*/
String sText = "深圳";
/**
* 默认后缀文字的宽高
*/
int sWitchPx;
int sHigthPx;
/**
* 第二段sText文字距离前一段文字的水平偏移量
*/
int offset = 80;
/**图片距离右边的距离*/
int right = 160;
/**图片距离上边的距离*/
int top = 100;
/**文字旋转的角度*/
float rotate =20f;
//设置背景
public void setWaterMarkTextBg(View view, Context gContext, String gText) {
view.setBackground(drawTextToBitmap(gContext, gText));
}
/**
* 生成水印文字图片
*/
public BitmapDrawable drawTextToBitmap(Context mContext, String gText) {
try {
TextPaint mTextPaint1 = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint1.density = mContext.getResources().getDisplayMetrics().density;
oneTextPx = DensityUtil.sp2px(mContext, textSize);
mTextPaint1.setTextSize(oneTextPx);
//计算字长
textLength = (int) mTextPaint1.measureText(gText);
int stextLength = (int) mTextPaint1.measureText(sText);
/**拿到字长之后,计算一下斜着显示文字的时候文字所占的长和高*/
int witchPx = 0;
int highPx = 0;
/**默认一段文字的长和高计算*/
if (sWitchPx == 0) {
sWitchPx = measurementWitch(stextLength);
sHigthPx = measurementHigth(stextLength);
}
/**传入的文字的长和高计算*/
witchPx = measurementWitch(textLength);
highPx = measurementHigth(textLength);
/**计算显示完整所需占的画图长宽*/
int bitmapWitch = witchPx + sWitchPx + 2 * oneTextPx + offset;
int bitmaphigth = (highPx + oneTextPx) * 2;
//设置画板的时候 增加一个字的长宽
Bitmap bitmap = Bitmap.createBitmap(bitmapWitch + right,
bitmaphigth+(2*top), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
/**初始化画笔*/
TextPaint mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.density = mContext.getResources().getDisplayMetrics().density;
mTextPaint.setColor(Color.GRAY);
mTextPaint.setAlpha(90);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setAntiAlias(true);
mTextPaint.setTextAlign(Paint.Align.LEFT);
mTextPaint.setFakeBoldText(false);
mTextPaint.setTextSkewX(0);
mTextPaint.setTextSize(oneTextPx);
/**
* ——————————————————————————————————>
* | 1号绘制区域 | 间 | 2号 |
* | gText | | appName |
* | ①号起点位置 | 隔 | ②起 |
* ———————————————————————————————————
* | 3号 | 间 | 4号绘制区域 |
* | appName | | gText |
* | ③起 | 隔 | ④号起 |
* |———————————————————————————————————
* V
*/
/**方式二利用画布平移和旋转绘制*/
/**先移动到①起点位置*/
canvas.translate(oneTextPx,highPx+oneTextPx+top);
/**旋转一定度数 绘制文字*/
canvas.rotate(-rotate);
canvas.drawText(gText,0,0,mTextPaint);
/**恢复原来的度数 再移动画布原点到②号位置*/
canvas.rotate(rotate);
canvas.translate(witchPx+offset+oneTextPx,0);
/**旋转一定度数 绘制文字*/
canvas.rotate(-rotate);
canvas.drawText(sText,0,0,mTextPaint);
/**恢复原来的度数 再移动画布原点到③号位置*/
canvas.rotate(rotate);
canvas.translate(-(witchPx+offset+oneTextPx),oneTextPx+highPx+top);
/**旋转一定度数 绘制文字*/
canvas.rotate(-rotate);
canvas.drawText(sText,0,0,mTextPaint);
/**恢复原来的度数 再移动画布原点到④号位置*/
canvas.rotate(rotate);
canvas.translate(sWitchPx+offset+oneTextPx,0);
/**旋转一定度数 绘制文字*/
canvas.rotate(-rotate);
canvas.drawText(gText,0,0,mTextPaint);
/**保存画布*/
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
//生成平铺的bitmapDrawable
BitmapDrawable drawable = new BitmapDrawable(mContext.getResources(), bitmap);
drawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
drawable.setDither(true);
return drawable;
} catch (Exception e) {
}
return null;
}
private int measurementWitch(int textLength) {
//t2 为字长的平方 字长的平方即为三角形的斜边的平方
int t2 = textLength * textLength;
//此处设置 三角形的长为高的3倍,那么就是平方之后的9倍,均分为10份 长占9份
return ceilInt(Math.sqrt(9 * (t2 / 10)));
}
private int measurementHigth(int textLength) {
//t2 为字长的平方 字长的平方即为三角形的斜边的平方
int t2 = textLength * textLength;
//此处设置 三角形的长为高的3倍,那么就是平方之后的9倍,均分为10份 长占9份
return ceilInt(Math.sqrt((t2 / 10)));
}
public static int ceilInt(double number) {
return (int) Math.ceil(number);
}
- 再贴一张效果图