项目中有需要加水印的需求,实现完效果图是这样的
为了让大家看清效果,字体改了一下,正常应该是文章最上面那个的效果。话不多说,直接上代码
import android.annotation.SuppressLint; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Typeface; import android.text.TextPaint; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import com.hkdc.commonlib.R; public class WaterMarkView extends View { private static final String DEFAULT_SEPARATOR = "///"; private TextPaint mTextPaint = new TextPaint(); private String[] mText; private int mDegrees; private int mTextColor; private int mTextSize=35; private boolean mTextBold; private int mDx; private int mDy; private Paint.Align mAlign; private boolean mSync; private int textWidth, textHeight; public WaterMarkView(Context context) { this(context, null); } public WaterMarkView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.WaterMarkView); mDegrees = typedArray.getInt(R.styleable.WaterMarkView_water_mark_degree, WaterMarkManager.INFO != null ? WaterMarkManager.INFO.getDegrees() : -30); String text = typedArray.getString(R.styleable.WaterMarkView_water_mark_text); if (text != null) { mText = text.split(DEFAULT_SEPARATOR); } mTextColor = typedArray.getColor(R.styleable.WaterMarkView_water_mark_textColor, WaterMarkManager.INFO != null ? WaterMarkManager.INFO.getTextColor() : Color.parseColor("#33000000")); mTextSize = typedArray.getDimensionPixelSize(R.styleable.WaterMarkView_water_mark_textSize, WaterMarkManager.INFO != null ? WaterMarkManager.INFO.getTextSize() : 42); mTextBold = typedArray.getBoolean(R.styleable.WaterMarkView_water_mark_textBold, WaterMarkManager.INFO != null && WaterMarkManager.INFO.isTextBold()); mDx = typedArray.getDimensionPixelSize(R.styleable.WaterMarkView_water_mark_dx, WaterMarkManager.INFO != null ? WaterMarkManager.INFO.getDx() : 100); mDy = typedArray.getDimensionPixelSize(R.styleable.WaterMarkView_water_mark_dy, WaterMarkManager.INFO != null ? WaterMarkManager.INFO.getDy() : 240); int align = typedArray.getInt(R.styleable.WaterMarkView_water_mark_align, WaterMarkManager.INFO != null ? WaterMarkManager.INFO.getAlignInt() : 1); mAlign = align == 0 ? Paint.Align.LEFT : align == 2 ? Paint.Align.RIGHT : Paint.Align.CENTER; mSync = typedArray.getBoolean(R.styleable.WaterMarkView_water_mark_sync, true); typedArray.recycle(); setBackgroundColor(Color.TRANSPARENT); mTextPaint.setAntiAlias(true); mTextPaint.setFlags(Paint.ANTI_ALIAS_FLAG); mTextPaint.setColor(mTextColor); mTextPaint.setTextSize(mTextSize); mTextPaint.setTypeface(mTextBold ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT); mTextPaint.setTextAlign(mAlign); mText = mText == null && mSync ? WaterMarkManager.CONTENT : mText; textWidth = 0; textHeight = 0; if (mText != null && mText.length > 0) { for (String s : mText) { Rect tvRect = new Rect(); mTextPaint.getTextBounds(s, 0, s.length(), tvRect); textWidth = textWidth > tvRect.width() ? textWidth : tvRect.width(); textHeight += (tvRect.height() + 10); } } if (mSync) { WaterMarkManager.LIST.add(this); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mText != null && mText.length > 0) { int measuredWidth = getMeasuredWidth(); int measuredHeight = getMeasuredHeight(); if (measuredWidth == 0 || measuredHeight == 0) { return; } int canvasLength = measuredWidth > measuredHeight ? measuredWidth : measuredHeight; canvas.save(); canvas.rotate(mDegrees, measuredWidth / 2, measuredHeight / 2); canvas.save(); int y = 0; boolean odd = true; while (y < canvasLength + textHeight) { int x = odd ? 0 : -(textWidth + mDx) / 2; while (x < canvasLength + textWidth) { drawTexts(mText, mTextPaint, canvas, x, y); x = x + textWidth + mDx; } y = y + textHeight + mDy; odd = !odd; } canvas.restore(); } } private void drawTexts(String[] ss, Paint paint, Canvas canvas, int x, int y) { Paint.FontMetrics fontMetrics = paint.getFontMetrics(); float top = fontMetrics.top; float bottom = fontMetrics.bottom; int length = ss.length; float total = (length - 1) * (bottom - top) + (fontMetrics.descent - fontMetrics.ascent); float offset = total / 2 - bottom; for (int i = 0; i < length; i++) { float yAxis = -(length - i - 1) * (bottom - top) + offset; canvas.drawText(ss[i], x, y + yAxis + 10, paint); } } /** * 设置水印文字内容 * * @param text 文字内容 */ public void setText(String... text) { mText = text; textWidth = 0; textHeight = 0; if (mText != null && mText.length > 0) { for (String s : mText) { Rect tvRect = new Rect(); mTextPaint.getTextBounds(s, 0, s.length(), tvRect); textWidth = textWidth > tvRect.width() ? textWidth : tvRect.width(); textHeight += (tvRect.height() + 10); } } postInvalidate(); } /** * 同步设置水印文字内容 * * @param text 文字内容 */ void setSyncText(String... text) { if (mSync) { setText(text); } } /** * 设置水印倾斜角度 * * @param degrees 倾斜角度(默认:-30) */ public void setDegrees(int degrees) { mDegrees = degrees; postInvalidate(); } /** * 同步设置水印倾斜角度 * * @param degrees 倾斜角度(默认:-30) */ void setSyncDegrees(int degrees) { if (mSync) { setDegrees(degrees); } } /** * 设置水印字体颜色 * * @param textColor 字体颜色(默认:#33000000) */ public void setTextColor(int textColor) { mTextColor = textColor; mTextPaint.setColor(mTextColor); postInvalidate(); } /** * 同步设置水印字体颜色 * * @param textColor 字体颜色(默认:#33000000) */ void setSyncTextColor(int textColor) { if (mSync) { setTextColor(textColor); } } /** * 设置水印字体大小(单位:px) * * @param textSize 字体大小(默认:42px) */ public void setTextSize(int textSize) { mTextSize = textSize; mTextPaint.setTextSize(30); postInvalidate(); } /** * 同步设置水印字体大小(单位:px) * * @param textSize 字体大小(默认:42px) */ void setSyncTextSize(int textSize) { if (mSync) { setTextSize(30); } } /** * 设置水印字体是否粗体 * * @param textBold 是否粗体(默认:false) */ public void setTextBold(boolean textBold) { mTextBold = textBold; mTextPaint.setTypeface(mTextBold ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT); postInvalidate(); } /** * 同步设置水印字体是否粗体 * * @param textBold 是否粗体(默认:false) */ void setSyncTextBold(boolean textBold) { if (mSync) { setTextBold(textBold); } } /** * 设置水印X轴偏移量(单位:px) * * @param dx X轴偏移量(默认:100px) */ public void setDx(int dx) { this.mDx = dx; postInvalidate(); } /** * 同步设置水印X轴偏移量(单位:px) * * @param dx X轴偏移量(默认:100px) */ void setSyncDx(int dx) { if (mSync) { setDx(dx); } } /** * 设置水印Y轴偏移量(单位:px) * * @param dy Y轴偏移量(默认:240px) */ public void setDy(int dy) { this.mDy = dy; postInvalidate(); } /** * 同步设置水印Y轴偏移量(单位:px) * * @param dy Y轴偏移量(默认:240px) */ void setSignDy(int dy) { if (mSync) { setDy(dy); } } /** * 设置水印对齐方式 * * @param align 对齐方式(默认:Center) */ public void setAlign(Paint.Align align) { this.mAlign = align; postInvalidate(); } /** * 同步设置水印对齐方式 * * @param align 对齐方式(默认:Center) */ void setSignAlign(Paint.Align align) { if (mSync) { setAlign(align); } } /** * 销毁相关页面时调用(切记) */ public void onDestroy() { if (mSync) { WaterMarkManager.LIST.remove(this); } } @Override public boolean dispatchTouchEvent(MotionEvent event) { return false; } @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { return false; } }
<!--warkmark--> <declare-styleable name="WaterMarkView"> <attr name="water_mark_degree" format="integer|reference" /> <attr name="water_mark_text" format="string|reference" /> <attr name="water_mark_textColor" format="color|reference" /> <attr name="water_mark_textSize" format="dimension|reference" /> <attr name="water_mark_textBold" format="boolean" /> <attr name="water_mark_dx" format="dimension|reference" /> <attr name="water_mark_dy" format="dimension|reference" /> <attr name="water_mark_align" format="dimension"> <enum name="LEFT" value="0" /> <enum name="CENTER" value="1" /> <enum name="RIGHT" value="2" /> </attr> <attr name="water_mark_sync" format="boolean" /> </declare-styleable>
package com.hkdc.commonlib.warkmark; import android.annotation.SuppressLint; import android.app.Activity; import android.graphics.Paint; import android.view.LayoutInflater; import com.hkdc.commonlib.R; import java.util.ArrayList; import java.util.List; /** * @author Leon (wshk729@163.com) * @date 2018/8/24 * <p> */ public class WaterMarkManager { static WaterMarkInfo INFO = null; static String[] CONTENT = null; static List<WaterMarkView> LIST = new ArrayList<>(); /** * 设置水印全局配置信息 * * @param info 配置信息 */ public static void setInfo(WaterMarkInfo info) { INFO = info; } /** * 获取一个满屏水印View * * @param activity activity */ @SuppressLint("InflateParams") public static WaterMarkView getView(Activity activity) { return (WaterMarkView) LayoutInflater.from(activity).inflate(R.layout.view_water_mark, null); } /** * WaterMarkInfo初始化判断 */ private static void assertInitialized() { if (INFO == null) { INFO = WaterMarkInfo.create().generate(); } } /** * 同步设置全部水印文字信息 * * @param content 文字信息 */ public static void setText(String... content) { assertInitialized(); CONTENT = content; if (LIST.size() > 0) { for (WaterMarkView view : LIST) { if (view != null) { view.setSyncText(content); } } } } /** * 同步设置全部水印倾斜角度 * * @param degrees 倾斜角度(默认:-30) */ public static void setDegrees(int degrees) { assertInitialized(); INFO.setDegrees(degrees); if (LIST.size() > 0) { for (WaterMarkView view : LIST) { if (view != null) { view.setSyncDegrees(degrees); } } } } /** * 同步设置全部水印字体颜色 * * @param textColor 字体颜色(默认:#33000000) */ public static void setTextColor(int textColor) { assertInitialized(); INFO.setTextColor(textColor); if (LIST.size() > 0) { for (WaterMarkView view : LIST) { if (view != null) { view.setSyncTextColor(textColor); } } } } /** * 同步设置全部水印字体大小(单位:px) * * @param textSize 字体大小(默认:42px) */ public static void setTextSize(int textSize) { assertInitialized(); INFO.setTextSize(textSize); if (LIST.size() > 0) { for (WaterMarkView view : LIST) { if (view != null) { view.setSyncTextSize(textSize); } } } } /** * 同步设置全部水印字体是否粗体 * * @param textBold 是否粗体(默认:false) */ public static void setTextBold(boolean textBold) { assertInitialized(); INFO.setTextBold(textBold); if (LIST.size() > 0) { for (WaterMarkView view : LIST) { if (view != null) { view.setSyncTextBold(textBold); } } } } /** * 同步设置全部水印X轴偏移量(单位:px) * * @param dx X轴偏移量(默认:100px) */ public static void setDx(int dx) { assertInitialized(); INFO.setDx(dx); if (LIST.size() > 0) { for (WaterMarkView view : LIST) { if (view != null) { view.setSyncDx(dx); } } } } /** * 同步设置全部水印Y轴偏移量(单位:px) * * @param dy Y轴偏移量(默认:240px) */ public static void setDy(int dy) { assertInitialized(); INFO.setDy(dy); if (LIST.size() > 0) { for (WaterMarkView view : LIST) { if (view != null) { view.setSignDy(dy); } } } } /** * 同步设置全部水印对齐方式 * * @param align 对齐方式(默认:Center) */ public static void setAlign(Paint.Align align) { assertInitialized(); INFO.setAlign(align); if (LIST.size() > 0) { for (WaterMarkView view : LIST) { if (view != null) { view.setSignAlign(align); } } } } }
view_water_mark.xml
<?xml version="1.0" encoding="utf-8"?> <com.commonlib.WaterMarkView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"/>
import android.graphics.Color; import android.graphics.Paint; /** * @author Leon (wshk729@163.com) * @date 2018/8/24 * <p> */ public class WaterMarkInfo { private int mDegrees; private int mTextColor; private int mTextSize; private boolean mTextBold; private int mDx; private int mDy; private Paint.Align mAlign; private WaterMarkInfo(int degrees, int textColor, int textSize, boolean textBold, int dx, int dy, Paint.Align align) { mDegrees = degrees; mTextColor = textColor; mTextSize = textSize; mTextBold = textBold; mDx = dx; mDy = dy; mAlign = align; } public int getDegrees() { return mDegrees; } public int getTextColor() { return mTextColor; } public int getTextSize() { return mTextSize; } public int getDx() { return mDx; } public int getDy() { return mDy; } public Paint.Align getAlign() { return mAlign; } public int getAlignInt() { switch (mAlign) { case LEFT: return 0; case RIGHT: return 2; default: return 1; } } public boolean isTextBold() { return mTextBold; } void setDegrees(int degrees) { mDegrees = degrees; } void setTextColor(int textColor) { mTextColor = textColor; } void setTextSize(int textSize) { mTextSize = textSize; } void setTextBold(boolean textBold) { mTextBold = textBold; } void setDx(int dx) { mDx = dx; } void setDy(int dy) { mDy = dy; } void setAlign(Paint.Align align) { this.mAlign = align; } public static Builder create() { return new Builder(); } public static class Builder { private int mDegrees; private int mTextColor; private int mTextSize; private boolean mTextBold; private int mDx; private int mDy; private Paint.Align mAlign; private Builder() { mDegrees = -30; mTextColor = Color.parseColor("#33000000"); mTextSize = 35; mTextBold = false; mDx = 100; mDy = 240; mAlign = Paint.Align.CENTER; } /** * 设置水印文字倾斜度 * * @param degrees 文字倾斜度(默认:-30) * @return Builder */ public Builder setDegrees(int degrees) { mDegrees = degrees; return this; } /** * 设置水印文字颜色 * * @param textColor 文字颜色(默认:#33000000) * @return Builder */ public Builder setTextColor(int textColor) { mTextColor = textColor; return this; } /** * 设置水印文字大小(单位:px) * * @param textSize 文字大小(默认:42px) * @return Builder */ public Builder setTextSize(int textSize) { mTextSize = textSize; return this; } /** * 设置水印文字是否加粗 * * @param textBold 文字加粗(默认:false) * @return Builder */ public Builder setTextBold(boolean textBold) { mTextBold = textBold; return this; } /** * 设置水印文字X轴间距(单位:px) * * @param dx 文字X轴间距(默认:100px) * @return Builder */ public Builder setDx(int dx) { mDx = dx; return this; } /** * 设置水印文字Y轴间距(单位:px) * * @param dy 文字Y轴间距(默认:240px) * @return Builder */ public Builder setDy(int dy) { mDy = dy; return this; } /** * 设置水印文字对齐方式 * * @param align 对齐方式(默认:Center) * @return Builder */ public Builder setAlign(Paint.Align align) { mAlign = align; return this; } /** * 生成水印全局配置信息 * * @return 配置信息 */ public WaterMarkInfo generate() { return new WaterMarkInfo(mDegrees, mTextColor, mTextSize, mTextBold, mDx, mDy, mAlign); } } }
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; import android.support.annotation.IntRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import java.util.List; public class WaterMarkBg extends Drawable { private Paint paint = new Paint(); private List<String> labels; private Context context; private int degress;//角度 private int fontSize;//字体大小 单位sp /** * 初始化构造 * @param context 上下文 * @param labels 水印文字列表 多行显示支持 * @param degress 水印角度 * @param fontSize 水印文字大小 */ public WaterMarkBg(Context context, List<String> labels, int degress, int fontSize) { this.labels = labels; this.context = context; this.degress = degress; this.fontSize = fontSize; } @Override public void draw(@NonNull Canvas canvas) { int width = getBounds().right; int height = getBounds().bottom; canvas.drawColor(Color.parseColor("#40F3F5F9")); paint.setColor(Color.parseColor("#50AEAEAE")); paint.setAntiAlias(true); paint.setTextSize(sp2px(context,fontSize)); canvas.save(); canvas.rotate(degress); float textWidth = paint.measureText(labels.get(0)); int index = 0; for (int positionY = height / 10; positionY <= height; positionY += height / 10+80) { float fromX = -width + (index++ % 2) * textWidth; for (float positionX = fromX; positionX < width; positionX += textWidth * 2) { int spacing = 0;//间距 for(String label:labels){ canvas.drawText(label, positionX, positionY+spacing, paint); spacing = spacing+50; } } } 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.UNKNOWN; } public static int sp2px(Context context, float spValue) { final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (spValue * fontScale + 0.5f); } }
xml中 引用
<com.commonlib.WaterMarkView android:singleLine="false" android:id="@+id/wm" android:layout_width="match_parent" android:layout_height="match_parent" app:water_mark_align="CENTER" app:water_mark_degree="-30" app:water_mark_dx="100px" app:water_mark_dy="240px" app:water_mark_sync="true" app:water_mark_text="再见孙悟空" app:water_mark_textBold="false" app:water_mark_textColor="@color/black" app:water_mark_textSize="30px" />
activity中
private WaterMarkView wm; wm = (WaterMarkView) findViewById(R.id.wm); private void water() { SharedPreferences jobcede = getSharedPreferences("jobcede", MODE_PRIVATE); String userName = jobcede.getString("username", ""); String name = jobcede.getString("name", ""); wm.setText(name,userName); }