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;
}
}
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
-
*/
public class WaterMarkManager {
static WaterMarkInfo INFO = null;
static String[] CONTENT = null;
static List 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
-
*/
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;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
相信它会给大家带来很多收获:
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
- 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!!
- 我希望每一个努力生活的IT工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。
当我们在抱怨环境,抱怨怀才不遇的时候,没有别的原因,一定是你做的还不够好!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-Yu4VsEAl-1712352240840)]
[外链图片转存中…(img-2ArBno7P-1712352240841)]
[外链图片转存中…(img-DViVdH8r-1712352240842)]
[外链图片转存中…(img-uuqtJK99-1712352240842)]
[外链图片转存中…(img-aj2475Py-1712352240842)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
相信它会给大家带来很多收获:
[外链图片转存中…(img-8LXIw7Cm-1712352240843)]
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
- 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!!
- 我希望每一个努力生活的IT工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。
当我们在抱怨环境,抱怨怀才不遇的时候,没有别的原因,一定是你做的还不够好!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!