从新写了一种更好的实现方式能够点下边的连接去看下
效果图以下
首先来讲下思路
由于咱们是要显示一个重复显示不少个的水印背景图,个人思路是绘制出一个文字是斜着的矩形图片,而后做为背景平铺。canvas
那么如何绘制带文字的矩形图片呢
首先咱们要绘制一个矩形上,那么矩形的对角线上显示的就是咱们的文字,文字根据绘制路径来绘制,主要是这个方法函数
Canvas.drawTextOnPath()工具
而后就是要绘制一条斜线,斜线的长度根据须要绘制的字符串长度来决定。字体
Paint mPaint = new Paint();
oneTextPx=DensityUtil.sp2px(mContext, textSize);
mPaint.setTextSize(oneTextPx);
//计算字长
textLength = (int) mPaint.measureText(gText);
知道了三角形的斜线长度以后,根据勾股定理,能够知道长宽的平方和是斜线的平方。spa
这里我 假设个人长是宽的三倍。而后就能够求出矩形的长宽了。.net
计算出长宽以后,考虑到文字是有高度的,那么绘制的矩形还须要更长一点。加入一点偏移量,恩,就给长宽都加上一个字长吧~rest
到此时咱们知道了画板的长宽,以及文字的绘制路径的坐标点了。code
首先绘制路径起点移动到斜矩形的左下角,而后设置移动到右下角的点;blog
//先移动到绘制路线的起始点,左下角
path.moveTo(10, highPx+oneTextPx);
//绘制的结束点
path.lineTo(witchPx, oneTextPx);
绘制好路径以后,就能够绘制文字了。
而后就能够生成bitmap图片了,以后就设置都须要设置背景的控件上去。
下边是一个关于文字绘制的图
斜的矩形是显示绘制文字的区域
横着的矩形是画板
贴一下完整的代码
/**
* 字的大小 单位sp
*/
final int textSize = 16;
/**
* 一个字所占的像素
*/
int oneTextPx;
/**
* 当前字符串所占的长度
*/
int textLength;
/**
* 默认后缀文字
*/
String sText = "深圳";
/**
* 默认后缀文字的宽高
*/
int sWitchPx;
int sHigthPx;
/**
* 第二段sText文字距离前一段文字的水平偏移量
*/
int offset = 40;
int right = 80;
/**
* 生成水印文字图片
*/
public BitmapDrawable drawTextToBitmap(Context mContext, String gText) {
gText = gText;
try {
Paint mPaint = new Paint();
oneTextPx = DensityUtil.sp2px(mContext, textSize);
mPaint.setTextSize(oneTextPx);
//计算字长
textLength = (int) mPaint.measureText(gText);
int stextLength = (int) mPaint.measureText(sText);
int witchPx = 0;
int highPx = 0;
if (sWitchPx == 0) {
sWitchPx = measurementWitch(stextLength);
sHigthPx = measurementHigth(stextLength);
}
witchPx = measurementWitch(textLength);
highPx = measurementHigth(textLength);
//设置画板的时候 增长一个字的长宽
Bitmap bitmap = Bitmap.createBitmap(witchPx + sWitchPx + 2 * oneTextPx + offset+right,
highPx + oneTextPx, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setColor(Color.GRAY);
paint.setAlpha(80);
paint.setAntiAlias(true);
paint.setTextAlign(Paint.Align.LEFT);
paint.setTextSize(oneTextPx);
Path path = new Path();
//传入文字的路径绘制
//先移动到绘制路线的起始点,左下角
path.moveTo(10, highPx + oneTextPx);
//绘制的结束点
path.lineTo(witchPx + oneTextPx, oneTextPx);
canvas.drawTextOnPath(gText, path, 0, 0, paint);
//重置路径,开始绘制默认文字路径
path.reset();
path.moveTo(witchPx + oneTextPx
+ 10 + offset, highPx + oneTextPx);
path.lineTo(witchPx + sWitchPx + 2 * oneTextPx + offset, highPx - sHigthPx + oneTextPx);
canvas.drawTextOnPath(sText, path, 0, 0, paint);
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
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(t2 - (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);
}
}
剩下的问题
如今就能够不须要顾及以前的文字长度的问题了,不过还有一个问题没有结局 o(╯□╰)o。
在不一样的机型上字体显示的有的出入比较大,考虑过多是屏幕密度的问题,获取了一下他们的值
貌似看起来差异不大,实际上一加5T上 字很小很小很小。。。。
暂时这个问题没有解决,有大神知道的。求指导!恩完了。
苍天大地绕过谁~终于找到这个文字在一些手机上显示太小的缘由了,搞了半天不是画笔计算的错误,是BitmapDrawable旧的过期的方法没有去设置密度,新的构造函数,能够正确设置其目标的密度。就是这一句话!换了目前就没有发现别的问题了。
Drawable drawable = new BitmapDrawable(bitmap);
BitmapDrawable drawable = new BitmapDrawable(mContext.getResources(),bitmap);
说一下这个问题解决的思路,由于一开始考虑的是画笔由于屏幕密度的致使变形的问题,而后看了一些TextView的源码,结果发现貌似TExtView算出的字体大小跟个人差很少,而后自定义了一个view,重写onDraw方法,绘制了文字 结果发现字体大小是正常的。因而开始考虑是否是转化成BitmapDrawable出了问题,发现BitmapDrawable的构造方法过期了,看了一下新的构造方法,结果发现新的构造方法里边设置了初始目标的密度,
而后果断一改运行,发现ok了!
天咧 终于找到这个坑了!
下边是2016年的代码o(╯□╰)o
--------------------------------------------------------2018年4月4日16:06:53-----------------------------------------------------------------------------------------------以上为更新内容----------------------------终于有时间回过头来看看这个问题了----------------------------------------如下为旧的-------------------------------------
先看效果:
先说实现方式:
一、首先先用文字建立一个Bitmap 图片。
Bitmap bitmap = Bitmap.createBitmap(420, 240, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setColor(Color.GRAY);
paint.setAlpha(80);
paint.setAntiAlias(true);
paint.setTextAlign(Paint.Align.LEFT);
paint.setTextSize(40);
Path path = new Path();
path.moveTo(0, 150);
path.lineTo(160 * 2, 0);
canvas.drawTextOnPath(gText, path, 0, 20, paint);
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
bitmap.recycle();在一个空白的背景上画出文字内容,此处的经过设置一个斜向上的path,而后在这个path上写文字,生成一个斜向上方形的文字。
最后获得一个Bitmap.
二、将生成的bitmap 一个view上
BitmapDrawable drawable = new BitmapDrawable(bitmap);
drawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
drawable.setDither(true);
view.setBackgroundDrawable(drawable );
最后贴上工具类代码:若是只想要背景图片 用drawTextToBitmap(), 若是要直接给一个view设置上背景 直接使用setWaterMarkTextBg()方法。
public class WaterMarkTextUtil {
//设置背景
public void setWaterMarkTextBg(View view, Context gContext, String gText) {
view.setBackgroundDrawable(drawTextToBitmap(gContext, gText));
}
/**
* 生成水印文字图片
*/
public BitmapDrawable drawTextToBitmap(Context gContext, String gText) {
gText=gText+" daydao";
if (ACache.get(gContext).getAsBitmap(gText) != null) {
BitmapDrawable drawable = new BitmapDrawable(ACache.get(gContext).getAsBitmap(gText));
drawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
drawable.setDither(true);
return drawable;
}
try {
Bitmap bitmap = Bitmap.createBitmap(420, 240, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setColor(Color.GRAY);
paint.setAlpha(80);
paint.setAntiAlias(true);
paint.setTextAlign(Paint.Align.LEFT);
paint.setTextSize(40);
Path path = new Path();
path.moveTo(0, 150);
path.lineTo(160 * 2, 0);
canvas.drawTextOnPath(gText, path, 0, 20, paint);
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
ACache.get(gContext).put(gText, bitmap);
BitmapDrawable drawable = new BitmapDrawable(bitmap);
drawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
drawable.setDither(true);
bitmap.recycle();
return drawable;
} catch (Exception e) {
}
return null;
}
}