1 #import <UIKit/UIKit.h>
2 @class NJLockView;
3
4 @protocol NJLockViewDelegate <NSObject>
5
6 - (void)lockViewDidClick:(NJLockView *)lockView andPwd:(NSString *)pwd;
7
8 @end
9
10 @interface NJLockView : UIView
11
12 @property (nonatomic, weak)IBOutlet id<NJLockViewDelegate> delegate;
13 @end
14
15
16
17 @interface NJLockView ()
18
19 @property (nonatomic, strong) NSMutableArray *buttons;
20 /**
21 * 定义属性,记录用户当前手指的位置(非按钮范围内)
22 */
23 @property (nonatomic, assign) CGPoint currentPoint;
24 @end
25
26 @implementation NJLockView
27
28
29 - (NSMutableArray *)buttons
30 {
31 if (_buttons == nil) {
32 _buttons = [NSMutableArray array];
33 }
34 return _buttons;
35 }
36
37 // 当视图是通过代码创建出来的就会调用initWithFrame
38 - (id)initWithFrame:(CGRect)frame
39 {
40 self = [super initWithFrame:frame];
41 if (self) {
42 // Initialization code
43 // NSLog(@"initWithFrame");
44 [self setup];
45 }
46 return self;
47 }
48
49 // 当视图从xib或storyboard中创建出来就会调用
50 - (id)initWithCoder:(NSCoder *)aDecoder
51 {
52 if (self = [super initWithCoder:aDecoder]) {
53 // 创建9个按钮
54 // NSLog(@"initWithCoder");
55 [self setup];
56
57 }
58 return self;
59 }
60
61 /**
62 * 创建9个按钮添加到自定view中
63 */
64 - (void)setup
65 {
66 for (int i = 0; i < 9; i++) {
67 // 1.创建按钮
68 UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
69 // 2.设置按钮的背景图片
70 [btn setBackgroundImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];
71
72 [btn setBackgroundImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected];
73
74 // 3.添加按钮到View
75 [self addSubview:btn];
76
77 // btn.backgroundColor = [UIColor redColor];
78
79 // 4.禁止按钮的点击事件(因为我们需要监听触摸事件)
80 btn.userInteractionEnabled = NO;
81
82 // 5.设置按钮的tag作为唯一标识
83 btn.tag = i;
84 }
85 }
86
87 - (void)layoutSubviews
88 {
89 [super layoutSubviews];
90 // 设置按钮的frame
91 for (int i = 0; i < self.subviews.count; i++) {
92 // 1.取出对应位置的按钮
93 UIButton *btn = self.subviews[i];
94
95 // 2.设置frame
96 CGFloat btnW = 74;
97 CGFloat btnH = 74;
98 // 2.1计算间距
99 CGFloat margin = (self.frame.size.width - (3 * btnW)) / 4;
100 int col = i % 3; // 列号
101 int row = i / 3; // 行号
102 // 间距 + 列号 * (按钮宽度+ 间距)
103 CGFloat btnX = margin + col * (btnW + margin);
104 CGFloat btnY = margin + row * (btnW + margin);
105
106 btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
107 }
108
109
110 }
111
112 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
113 {
114 // 1.获取按下的点
115 CGPoint startPoint = [self getCurrentTouchPoint:touches];
116
117 // 2.判断触摸的位置是否在按钮的范围内
118 UIButton *btn = [self getCurrentBtnWithPoint:startPoint];
119
120 // 存储按钮
121 if (btn)
122 {
123 // 设置选中状态
124 btn.selected = YES;
125 // 将按钮保存到数组中
126 [self.buttons addObject:btn];
127 }
128
129 btn.selected = YES;
130
131 // [self setNeedsDisplay];
132
133 }
134
135 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
136 {
137 // 1.获取按下的点
138 CGPoint movePoint = [self getCurrentTouchPoint:touches];
139 // 2.获取触摸的按钮
140 UIButton *btn = [self getCurrentBtnWithPoint:movePoint];
141
142 // 存储按钮
143 if (btn && btn.selected != YES)
144 {
145 // 设置选中状态
146 btn.selected = YES;
147 // 将按钮保存到数组中
148 [self.buttons addObject:btn];
149 }
150 // 记录当前手指移动的位置
151 self.currentPoint = movePoint;
152
153 // 通知view绘制线段
154 [self setNeedsDisplay];
155
156 }
157
158 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
159 {
160
161 // 取出用户输入的密码
162 NSMutableString *result = [NSMutableString string];
163 for (UIButton *btn in self.buttons) {
164 [result appendFormat:@"%d", btn.tag ];
165 }
166 // NSLog(@"result = %@", result);
167 // 通知代理,告诉代理用户输入的密码
168 if ([self.delegate respondsToSelector:@selector(lockViewDidClick:andPwd:)]) {
169 [self.delegate lockViewDidClick:self andPwd:result];
170 }
171
172 [self.buttons makeObjectsPerformSelector:@selector(setSelected:) withObject:@(NO)];
173
174 // 清空数组
175 [self.buttons removeAllObjects];
176 [self setNeedsDisplay];
177
178 // 清空currentPoint
179 self.currentPoint = CGPointZero;
180 }
181
182
183 - (void)drawRect:(CGRect)rect
184 {
185
186 CGContextRef ctx = UIGraphicsGetCurrentContext();
187
188 // 清空上下文
189 CGContextClearRect(ctx, rect);
190
191 // 从数组中取出所有的按钮, 连接所有按钮的中点
192 for (int i = 0; i < self.buttons.count; i++) {
193 // 取出按钮
194 UIButton *btn = self.buttons[i];
195 if (0 == i) {
196 CGContextMoveToPoint(ctx, btn.center.x, btn.center.y);
197 }else
198 {
199 CGContextAddLineToPoint(ctx, btn.center.x, btn.center.y);
200 }
201 }
202
203 // 判断如果当前点是00就不会只
204 // if (!CGPointEqualToPoint(self.currentPoint, CGPointZero)) {
205 //
206 // // 当所有的按钮的中点都连接号之后再连接手指当前的位置
207 // CGContextAddLineToPoint(ctx, self.currentPoint.x, self.currentPoint.y);
208 // }
209
210 // 判断数组中是否有按钮, 如果有按钮就有起点, 有起点就不会报错
211 if (self.buttons.count != 0) {
212
213 CGContextAddLineToPoint(ctx, self.currentPoint.x, self.currentPoint.y);
214 }
215
216
217 // [[UIColor greenColor] set];
218
219 [[UIColor colorWithRed:18/255.0 green:102/255.0 blue:72/255.0 alpha:0.5] set];
220 CGContextSetLineWidth(ctx, 10);
221 CGContextSetLineJoin(ctx, kCGLineJoinRound);
222 CGContextSetLineCap(ctx, kCGLineCapRound);
223 CGContextStrokePath(ctx);
224 }
225
226 /**
227 * 根据系统传入的UITouch集合获取当前触摸的点
228 * @return 当初触摸的点
229 */
230 - (CGPoint)getCurrentTouchPoint:(NSSet *)touches
231 {
232 // 1.获取按下的点
233 UITouch *touch = [touches anyObject];
234 CGPoint point = [touch locationInView:touch.view];
235 return point;
236 }
237
238 /**
239 * 根据触摸点获取触摸到的按钮
240 * @return 触摸的按钮
241 */
242 - (UIButton *)getCurrentBtnWithPoint:(CGPoint)point
243 {
244 // 2.判断触摸的位置是否在按钮的范围内
245 for (UIButton *btn in self.subviews) {
246 //
247 if (CGRectContainsPoint(btn.frame, point)) {
248 return btn;
249 }
250 }
251 return nil;
252 }
253 @end