思路:
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