首页 > 代码库 > iOS开发UI篇—实现一个简单的手势解锁应用(完善)
iOS开发UI篇—实现一个简单的手势解锁应用(完善)
iOS开发UI篇—实现一个简单的手势解锁应用(完善)
一、需要实现的效果
二、应用完善
1.绘制不处于按钮范围内的连线
2.解决bug(完善)
bug1:如果在began方法中通知view绘图,那么会产生bug。因为,当前点没有清空,在手指移开之后要清空当前点。可以在绘制前进行判断,如果当前点是(0,0)那么就不划线。或者在began方法中不进行重绘。
bug2:无限菊花。自定义view的背景色为默认的(黑色),只要重写了drawrect方法,view默认的背景颜色就是黑色的,因为上下文默认的颜色是黑色的。会有缓存,出现无限菊花。可以通过在每次绘制前对上下文进行清空。
调整后的效果:
注意点:当自定义view的背景颜色为默认的时候,会有缓存。
bug3:没有当前点(没有起点)。判断数组中是否有按钮,如果有按钮,那么就有起点不会报错。
三、获取用户输入的手势密码
实现效果:
获取用户的手势(密码)
思路:当用户手指离开屏幕的时候,获取用户输入的密码(手势)。需要每个按钮表示一个唯一的数字,可以考虑使用tag值,作为按钮的唯一标识。创建一个可变的字符串,通过一个循环,把数组中的每个按钮的tag值添加到可变字符串中。
提示:考虑把获取用户输入密码环节进行封装。比较用户密码是否正确应该在控制器的业务逻辑中进行处理。
思路:自定义一个协议,设置代理,获取用户输入的密码后,告诉代理用户输入的密码。
设置代理
代码:
在自定义view的头文件YYLockView.h中自定义一个协议。
1 // 2 // YYLockView.h 3 // 01-手势解锁(基本) 4 // 5 // Created by apple on 14-6-18. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h>10 11 @class YYLockView;12 @protocol YYLockViewDelegate <NSObject>13 //自定义一个协议14 //协议方法,把当前视图作为参数15 -(void)LockViewDidClick:(YYLockView *)lockView andPwd:(NSString *)pwd;16 @end17 18 @interface YYLockView : UIView19 //代理20 @property(nonatomic,weak) IBOutlet id<YYLockViewDelegate>delegate;21 @end
在Touchesended方法中通知代理
1 //取出用户输入的密码 2 //创建一个可变的字符串,用来保存用户密码 3 NSMutableString *result=[NSMutableString string]; 4 for (UIButton *btn in self.buttons) { 5 [result appendFormat:@"%d",btn.tag]; 6 } 7 NSLog(@"用户输入的密码为:%@",result); 8 //通知代理,告知用户输入的密码 9 if ([self.delegate respondsToSelector:@selector(LockViewDidClick:andPwd:)]) {10 [self.delegate LockViewDidClick:self andPwd:result];11 }
在主控制器中实现协议中的方法
1 #import "YYViewController.h" 2 #import "YYLockView.h" 3 4 @interface YYViewController ()<YYLockViewDelegate> 5 6 @end 7 8 @implementation YYViewController 9 10 - (void)viewDidLoad11 {12 [super viewDidLoad];13 }14 15 -(void)LockViewDidClick:(YYLockView *)lockView andPwd:(NSString *)pwd16 {17 NSLog(@"密码=%@",pwd);18 }19 @end
四、附录
完整代码:
自定义的view中,YYLockView.m文件
1 // 2 // YYLockView.m 3 // 01-手势解锁(基本) 4 // 5 // Created by apple on 14-6-18. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import "YYLockView.h" 10 11 @interface YYLockView () 12 @property(nonatomic,strong)NSMutableArray *buttons; 13 //定义一个属性,记录当前点 14 @property(nonatomic,assign)CGPoint currentPoint; 15 @end 16 @implementation YYLockView 17 18 #pragma mark-懒加载 19 -(NSMutableArray *)buttons 20 { 21 if (_buttons==nil) { 22 _buttons=[NSMutableArray array]; 23 } 24 return _buttons; 25 } 26 27 //界面搭建 28 - (id)initWithFrame:(CGRect)frame 29 { 30 self = [super initWithFrame:frame]; 31 if (self) { 32 [self setup]; 33 } 34 return self; 35 } 36 37 -(id)initWithCoder:(NSCoder *)aDecoder 38 { 39 if (self=[super initWithCoder:aDecoder]) { 40 [self setup]; 41 } 42 return self; 43 } 44 //在界面上创建9个按钮 45 -(void)setup 46 { 47 //1.创建9个按钮 48 for (int i=0; i<9; i++) { 49 UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom]; 50 //2.设置按钮的状态背景 51 [btn setBackgroundImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal]; 52 [btn setBackgroundImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected]; 53 //3.把按钮添加到视图中 54 [self addSubview:btn]; 55 //4.禁止按钮的点击事件 56 btn.userInteractionEnabled=NO; 57 //5.设置每个按钮的tag 58 btn.tag=i; 59 } 60 } 61 62 //4.设置按钮的frame 63 -(void)layoutSubviews 64 { 65 //4.1需要先调用父类的方法 66 [super layoutSubviews]; 67 for (int i=0; i<self.subviews.count; i++) { 68 //4.2取出按钮 69 UIButton *btn=self.subviews[i]; 70 71 //4.3九宫格法计算每个按钮的frame 72 CGFloat row = i/3; 73 CGFloat loc = i%3; 74 CGFloat btnW=74; 75 CGFloat btnH=74; 76 CGFloat padding=(self.frame.size.width-3*btnW)/4; 77 CGFloat btnX=padding+(btnW+padding)*loc; 78 CGFloat btnY=padding+(btnW+padding)*row; 79 btn.frame=CGRectMake(btnX, btnY, btnW, btnH); 80 } 81 } 82 83 //5.监听手指的移动 84 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 85 { 86 CGPoint starPoint=[self getCurrentPoint:touches]; 87 UIButton *btn=[self getCurrentBtnWithPoint:starPoint]; 88 89 if (btn && btn.selected != YES) { 90 btn.selected=YES; 91 [self.buttons addObject:btn]; 92 } 93 // [self setNeedsDisplay]; 94 } 95 96 -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 97 { 98 CGPoint movePoint=[self getCurrentPoint:touches]; 99 UIButton *btn=[self getCurrentBtnWithPoint:movePoint];100 //存储按钮101 //已经连过的按钮,不可再连102 if (btn && btn.selected != YES) {103 //设置按钮的选中状态104 btn.selected=YES;105 //把按钮添加到数组中106 [self.buttons addObject:btn];107 }108 //记录当前点(不在按钮的范围内)109 self.currentPoint=movePoint;110 //通知view重新绘制111 [self setNeedsDisplay];112 }113 114 //手指离开的时候清除线条115 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event116 {117 //取出用户输入的密码118 //创建一个可变的字符串,用来保存用户密码119 NSMutableString *result=[NSMutableString string];120 for (UIButton *btn in self.buttons) {121 [result appendFormat:@"%d",btn.tag];122 }123 NSLog(@"用户输入的密码为:%@",result);124 //通知代理,告知用户输入的密码125 if ([self.delegate respondsToSelector:@selector(LockViewDidClick:andPwd:)]) {126 [self.delegate LockViewDidClick:self andPwd:result];127 }128 129 //重置按钮的状态130 // for (UIButton *btn in self.buttons) {131 // btn.selected=NO;132 //// [btn setSelected:NO];133 // }134 135 //调用该方法,它就会让数组中的每一个元素都调用setSelected:方法,并给每一个元素传递一个NO参数136 [self.buttons makeObjectsPerformSelector:@selector(setSelected:) withObject:@(NO)];137 //清空数组138 [self.buttons removeAllObjects];139 [self setNeedsDisplay];140 141 //清空当前点142 self.currentPoint=CGPointZero;143 }144 145 //对功能点进行封装146 -(CGPoint)getCurrentPoint:(NSSet *)touches147 {148 UITouch *touch=[touches anyObject];149 CGPoint point=[touch locationInView:touch.view];150 return point;151 }152 -(UIButton *)getCurrentBtnWithPoint:(CGPoint)point153 {154 for (UIButton *btn in self.subviews) {155 if (CGRectContainsPoint(btn.frame, point)) {156 return btn;157 }158 }159 return Nil;160 }161 162 //重写drawrect:方法163 -(void)drawRect:(CGRect)rect164 {165 //获取上下文166 CGContextRef ctx=UIGraphicsGetCurrentContext();167 //在每次绘制前,清空上下文168 CGContextClearRect(ctx, rect);169 170 //绘图(线段)171 for (int i=0; i<self.buttons.count; i++) {172 UIButton *btn=self.buttons[i];173 if (0==i) {174 //设置起点(注意连接的是中点)175 // CGContextMoveToPoint(ctx, btn.frame.origin.x, btn.frame.origin.y);176 CGContextMoveToPoint(ctx, btn.center.x, btn.center.y);177 }else178 {179 // CGContextAddLineToPoint(ctx, btn.frame.origin.x, btn.frame.origin.y);180 CGContextAddLineToPoint(ctx, btn.center.x, btn.center.y);181 }182 }183 184 //当所有按钮的中点都连接好之后,再连接手指当前的位置185 //判断数组中是否有按钮,只有有按钮的时候才绘制186 if (self.buttons.count !=0) {187 CGContextAddLineToPoint(ctx, self.currentPoint.x, self.currentPoint.y);188 }189 190 //渲染191 //设置线条的属性192 CGContextSetLineWidth(ctx, 10);193 CGContextSetLineJoin(ctx, kCGLineJoinRound);194 CGContextSetLineCap(ctx, kCGLineCapRound);195 CGContextSetRGBStrokeColor(ctx, 20/255.0, 107/255.0, 153/255.0, 1);196 CGContextStrokePath(ctx);197 }198 @end
YYLockView.h文件代码
1 // 2 // YYLockView.h 3 // 01-手势解锁(基本) 4 // 5 // Created by apple on 14-6-18. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h>10 11 @class YYLockView;12 @protocol YYLockViewDelegate <NSObject>13 //自定义一个协议14 //协议方法,把当前视图作为参数15 -(void)LockViewDidClick:(YYLockView *)lockView andPwd:(NSString *)pwd;16 @end17 18 @interface YYLockView : UIView19 //代理20 @property(nonatomic,weak) IBOutlet id<YYLockViewDelegate>delegate;21 @end
主控制器文件
1 // 2 // YYViewController.m 3 // 01-手势解锁(基本) 4 // 5 // Created by apple on 14-6-18. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import "YYViewController.h"10 #import "YYLockView.h"11 12 @interface YYViewController ()<YYLockViewDelegate>13 14 @end15 16 @implementation YYViewController17 18 - (void)viewDidLoad19 {20 [super viewDidLoad];21 }22 23 -(void)LockViewDidClick:(YYLockView *)lockView andPwd:(NSString *)pwd24 {25 NSLog(@"密码=%@",pwd);26 }27 @end
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。