前言
为了防止工程师泄露用户信息,我们有个需求是在列表上面添加水印。我封装了这个视图分享出来。下面话不多说了,来一起看看详细的介绍吧
效果图
示例代码如下:
watermarkview.h
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#import <uikit/uikit.h> @interface watermarkview : uiimageview /** 设置水印 @param frame 水印大小 @param marktext 水印显示的文字 */ - (instancetype)initwithframe:(cgrect)frame withtext:(nsstring *)marktext; @end |
watermarkview.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#import "watermarkview.h" #define horizontal_space 30//水平间距 #define vertical_space 50//竖直间距 #define cg_transform_rotation (m_pi_2 / 3)//旋转角度(正旋45度 || 反旋45度) @implementation watermarkview - (instancetype)initwithframe:(cgrect)frame withtext:(nsstring *)marktext{ if (self = [super initwithframe:frame]){ uifont *font = [uifont systemfontofsize:14]; uicolor *color = ythcoloralpha(152, 152, 152, 0.1); //原始image的宽高 cgfloat viewwidth = frame.size.width; cgfloat viewheight = frame.size.height; //为了防止图片失真,绘制区域宽高和原始图片宽高一样 uigraphicsbeginimagecontext(cgsizemake(viewwidth, viewheight)); //sqrtlength:原始image的对角线length。在水印旋转矩阵中只要矩阵的宽高是原始image的对角线长度,无论旋转多少度都不会有空白。 cgfloat sqrtlength = sqrt (viewwidth*viewwidth + viewheight*viewheight); //文字的属性 nsdictionary *attr = @{ //设置字体大小 nsfontattributename: font, //设置文字颜色 nsforegroundcolorattributename :color, }; nsstring* mark = marktext; nsmutableattributedstring *attrstr = [[nsmutableattributedstring alloc] initwithstring:mark attributes:attr]; //绘制文字的宽高 cgfloat strwidth = attrstr.size.width; cgfloat strheight = attrstr.size.height; //开始旋转上下文矩阵,绘制水印文字 cgcontextref context = uigraphicsgetcurrentcontext(); //将绘制原点(0,0)调整到原image的中心 cgcontextconcatctm(context, cgaffinetransformmaketranslation(viewwidth/2, viewheight/2)); //以绘制原点为中心旋转 cgcontextconcatctm(context, cgaffinetransformmakerotation(cg_transform_rotation)); //将绘制原点恢复初始值,保证当前context中心和源image的中心处在一个点(当前context已经旋转,所以绘制出的任何layer都是倾斜的) cgcontextconcatctm(context, cgaffinetransformmaketranslation(-viewwidth/2, -viewheight/2)); //计算需要绘制的列数和行数 int horcount = sqrtlength / (strwidth + horizontal_space) + 1; int vercount = sqrtlength / (strheight + vertical_space) + 1; //此处计算出需要绘制水印文字的起始点,由于水印区域要大于图片区域所以起点在原有基础上移 cgfloat orignx = -(sqrtlength-viewwidth)/2; cgfloat origny = -(sqrtlength-viewheight)/2; //在每列绘制时x坐标叠加 cgfloat temporignx = orignx; //在每行绘制时y坐标叠加 cgfloat temporigny = origny; for ( int i = 0; i < horcount * vercount; i++) { [mark drawinrect:cgrectmake(temporignx, temporigny, strwidth, strheight) withattributes:attr]; if (i % horcount == 0 && i != 0) { temporignx = orignx; temporigny += (strheight + vertical_space); } else { temporignx += (strwidth + horizontal_space); } } //根据上下文制作成图片 uiimage *finalimg = uigraphicsgetimagefromcurrentimagecontext(); uigraphicsendimagecontext(); cgcontextrestoregstate(context); self.image = finalimg; } return self; } -(uiview *)hittest:(cgpoint)point withevent:(uievent *)event{ //1.判断自己能否接收事件 if (self.userinteractionenabled == no || self.hidden == yes || self.alpha <= 0.01) { return nil; } //2.判断当前点在不在当前view. if (![self pointinside:point withevent:event]) { return nil; } //3.从后往前遍历自己的子控件.让子控件重复前两步操作,(把事件传递给,让子控件调用hittest) int count = ( int )self.subviews.count; for ( int i = count - 1; i >= 0; i--) { //取出每一个子控件 uiview *chilev = self.subviews[i]; //把当前的点转换成子控件坐标系上的点. cgpoint childp = [self convertpoint:point toview:chilev]; uiview *fitview = [chilev hittest:childp withevent:event]; //判断有没有找到最适合的view if (fitview){ return fitview; } } //4.没有找到比它自己更适合的view.那么它自己就是最适合的view return self; } //作用:判断当前点在不在它调用view,(谁调用pointinside,这个view就是谁) //什么时候调用:它是在hittest方法当中调用的. //注意:point点必须得要跟它方法调用者在同一个坐标系里面 -( bool )pointinside:(cgpoint)point withevent:(uievent *)event{ nslog(@ "%s" ,__func__); return no; } |
使用方法
1
2
3
|
//加水印 watermarkview *watermark = [[watermarkview alloc] initwithframe:cgrectmake(0, 0, kscreenw, kscreenh) withtext:@ "测试" ]; [self.view addsubview:watermark]; |
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:https://www.jianshu.com/p/baf2bfe3de89