思路:

1.画9个按钮,通过按钮的选中状态控制按钮.

2.连线通过贝塞尔曲线绘制.

3.校验密码通过给按钮绑定tag值判断.

主要代码:

OC版本:

  1 //
  2 //  NineLockView.m
  3 //  lockView
  4 //
  5 //  Created by Shaoting Zhou on 2018/1/24.
  6 //  Copyright © 2018年 Shaoting Zhou. All rights reserved.
  7 //
  8 
  9 #import "NineLockView.h"
 10 
 11 CGFloat const btnCount = 9; //九宫格个数
 12 CGFloat const btnW = 74;    //单个按钮宽
 13 CGFloat const btnH = 74;    //单个按钮高
 14 CGFloat const viewY = 300;  //视图Y
 15 int const columnCount = 3;   //列数
 16 #define kScreenWidth [UIScreen mainScreen].bounds.size.width
 17 
 18 @interface NineLockView ()
 19 @property (nonatomic, strong) NSMutableArray * selectBtnsAry; //选中按钮的数组
 20 @property (nonatomic, assign) CGPoint currentPoint;    //当前的点 坐标 用于判断最后一个点
 21 @end
 22 
 23 
 24 @implementation NineLockView
 25 
 26 -(NSMutableArray *)selectBtnsAry{
 27     if(!_selectBtnsAry){
 28         _selectBtnsAry = [NSMutableArray array];
 29     }
 30     return _selectBtnsAry;
 31 }
 32 
 33 //通过代码布局时会调用这个方法
 34 -(instancetype)initWithFrame:(CGRect)frame{
 35     if(self = [super initWithFrame:frame]){
 36         self.backgroundColor = [UIColor clearColor];
 37         [self addButton];
 38     }
 39     return self;
 40 }
 41 
 42 //通过sb xib布局时会调用这个方法
 43 -(instancetype)initWithCoder:(NSCoder *)aDecoder{
 44     if(self = [super initWithCoder:aDecoder]){
 45         [self addButton];
 46     }
 47     return self;
 48 }
 49 
 50 #pragma Mark - 布局按钮
 51 - (void)addButton{
 52     CGFloat height = 0;;
 53     for (int i = 0; i < btnCount; i++) {
 54         UIButton * btn = [UIButton buttonWithType:(UIButtonTypeCustom)];
 55         btn.tag = i;
 56         btn.userInteractionEnabled = NO; //不可交互
 57         //设置默认的图片
 58         [btn setBackgroundImage:[UIImage imageNamed:@"gesture_normal"] forState:(UIControlStateNormal)];
 59         //设置选中的图片
 60         [btn setBackgroundImage:[UIImage imageNamed:@"gesture_selected"] forState:(UIControlStateSelected)];
 61         int row = i / columnCount;  //第几行
 62         int column = i % columnCount;   //第几列
 63         CGFloat margin = (self.frame.size.width - columnCount * btnW) / (columnCount + 1); //边距
 64         CGFloat btnX = margin + column * (btnW + margin);   //x轴
 65         CGFloat btnY = row * (btnW + margin);       //y轴
 66 //        btn.backgroundColor =[UIColor redColor];
 67         btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
 68         height = btnH + btnY;   //视图高等于 最后一个点的高+y
 69         [self addSubview:btn];
 70     }
 71     self.frame = CGRectMake(0, viewY, kScreenWidth, height);   //视图frame
 72 }
 73 
 74 
 75 - (CGPoint)pointWithTouch:(NSSet *)touches{
 76     UITouch * touch = [touches anyObject];
 77     CGPoint point = [touch locationInView:self];
 78     return point;
 79 }
 80 - (UIButton *)buttonWithPoint:(CGPoint)point{
 81     for (UIButton * btn in self.subviews) {
 82         if(CGRectContainsPoint(btn.frame, point)){
 83             return btn;
 84         }
 85     }
 86     return nil;
 87 }
 88 
 89 
 90 #pragma Mark - 开始移动
 91 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
 92     //1.拿到触摸的点
 93     CGPoint point = [self pointWithTouch:touches];
 94     //2.根据触摸的点拿到相应的按钮
 95     UIButton * btn = [self buttonWithPoint:point];
 96     //3.设置状态
 97     if(btn && btn.selected == NO){
 98         btn.selected = YES;
 99         [self.selectBtnsAry addObject:btn];
100     }
101     
102     
103 }
104 
105 #pragma Mark  - 移动中
106 - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
107     //1.拿到触摸的点
108     CGPoint point = [self pointWithTouch:touches];
109     //2.根据触摸的点拿到相应的按钮
110     UIButton * btn = [self buttonWithPoint:point];
111     //3.设置状态
112     if(btn && btn.selected == NO){
113         btn.selected = YES;
114         [self.selectBtnsAry addObject:btn];
115     }else{
116         self.currentPoint = point;
117     }
118     [self setNeedsDisplay];
119 }
120 
121 #pragma Mark - 结束移动
122 - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
123     if([self.delegete respondsToSelector:@selector(lockView:didFinishPath:)]){
124         NSMutableString * path = [NSMutableString string];
125         for (UIButton * btn in self.selectBtnsAry) {
126             [path appendFormat:@"%ld",(long)btn.tag];
127         }
128         [self.delegete lockView:self didFinishPath:path];
129     }
130     //清空状态
131     for(int i = 0; i < self.selectBtnsAry.count; i++ ){
132         UIButton * button = self.selectBtnsAry[i];
133         button.selected = NO;
134     }
135     [self.selectBtnsAry removeAllObjects];
136     [self setNeedsDisplay];
137 }
138 
139 #pragma  Mark - 取消移动
140 - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
141     [self touchesEnded:touches withEvent:event];
142 }
143 
144 #pragma Mark - 绘图
145 - (void)drawRect:(CGRect)rect{
146     if(self.selectBtnsAry.count  == 0){
147         return;
148     }
149     UIBezierPath * path = [UIBezierPath bezierPath];
150     path.lineWidth = 8;
151     path.lineJoinStyle = kCGLineJoinRound;
152     [[UIColor colorWithRed:32/255.0 green:210/255.0 blue:254/255.0 alpha:0.5] set];
153     //遍历按钮
154     for(int i = 0; i < self.selectBtnsAry.count; i++ ){
155         UIButton * button = self.selectBtnsAry[i];
156         NSLog(@"%d",i);
157         if(i == 0){
158             //设置起点
159             [path moveToPoint:button.center];
160         }else{
161             //连线
162             [path addLineToPoint:button.center];
163         }
164 
165     }
166     [path addLineToPoint:self.currentPoint]; //最后一点 连接自己
167     [path stroke];
168 
169 }
170 
171 
172 
173 
174 @end
OC版本

相关文章: