手势滑动解锁
2016-02-01 16:03
295 查看
思路
遍历生成且设置按钮当手指点击或者滑动的时候拿到当前触摸点,遍历每一个按钮,将当前触摸点转换为按钮上点,判断时候在按钮上
如果在按钮上,设置当前按钮为选中状态,添加到选中按钮数组中
在drawInRect:中画线,遍历每一个按钮,让第一个按钮的中心点为线段的起点
松开手指时,清空选中按钮数组中的值,重绘
@interface LockView () @property (nonatomic, assign) CGPoint curP; @property (nonatomic, strong) NSMutableArray *selectedBtns; @end @implementation LockView - (NSMutableArray *)selectedBtns { if (_selectedBtns == nil) { _selectedBtns = [NSMutableArray array]; } return _selectedBtns; } // 画线 // drawRect每次调用,都会把之前的内容全部清空 - (void)drawRect:(CGRect)rect { // 没有选中按钮就不画线 if (self.selectedBtns.count == 0) return; // 拼接路径 UIBezierPath *path = [UIBezierPath bezierPath]; int i = 0; // 连接所有的选中按钮 for (UIButton *selBtn in self.selectedBtns) { if (i == 0) { // 设置起点,起点是第一个选中按钮的中心点 [path moveToPoint:selBtn.center]; }else{ [path addLineToPoint:selBtn.center]; } i++; } // 添加一根线到手势的触摸点 [path addLineToPoint:_curP]; // 颜色 [[UIColor greenColor] set]; // 设置路径的线宽 path.lineWidth = 10; path.lineJoinStyle = kCGLineJoinRound; // 画线 [path stroke]; } // 手指在手势解锁view点击的时候调用 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 选中按钮 [self selectBtnWithTouches:touches withEvent:event]; } // 手指在手势解锁view移动的时候调用 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { // 选中按钮 [self selectBtnWithTouches:touches withEvent:event]; // 重绘 [self setNeedsDisplay]; } // 手指在手势解锁view抬起的时候调用 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { NSMutableString *strM = [NSMutableString string]; // 让所有选中按钮恢复成正常状态 for (UIButton *selBtn in self.selectedBtns) { selBtn.selected = NO; // 拼接密码字符串 [strM appendFormat:@"%ld",selBtn.tag]; } NSLog(@"%@",strM); // 清空选中按钮数组 [self.selectedBtns removeAllObjects]; // 把之前绘制线清空 [self setNeedsDisplay]; } // 选中按钮 - (void)selectBtnWithTouches:(NSSet *)touches withEvent:(UIEvent *)event { // UITouch UITouch *touch = [touches anyObject]; // 获取当前触摸点 CGPoint curP = [touch locationInView:self]; // 记录下当前移动触摸点 _curP = curP; // 判断下在不在按钮上 for (UIButton *btn in self.subviews) { // 转换成按钮坐标系上的点 CGPoint btnP = [self convertPoint:curP toView:btn]; // 判断当前点在按钮上并且按钮没有选中 if ([btn pointInside:btnP withEvent:event] && btn.selected == NO) { // 点在按钮上,把按钮选中 btn.selected = YES; // 记录选中的按钮 [self.selectedBtns addObject:btn]; } } } // 当从xib加载完成的时候调用 - (void)awakeFromNib { // 添加9个按钮 for (int i = 0; i < 9; i++) { UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; btn.tag = i; // 正常 [btn setImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal]; // 选中:选中状态下的图片可以一直保持 [btn setImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected]; // 如何判断按钮的图片是高亮还是选中,选中状态的图片可以一直保持 // 按钮的选中状态只能通过代码实现 // 按钮的高亮状态是系统默认达到,只要当用户一点击按钮,系统就会自动让达到高亮状态 btn.userInteractionEnabled = NO; // 监听按钮的点击 // [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown]; // // btn.adjustsImageWhenHighlighted = NO; [self addSubview:btn]; } } // 点击按钮的时候调用 //- (void)btnClick:(UIButton *)btn //{ // // 把按钮选中 // btn.selected = YES; //} // 设置按钮的位置 // 只要父控件的尺寸确认,就会调用 - (void)layoutSubviews { [super layoutSubviews]; int col = 0; int row = 0; int cols = 3; CGFloat x = 0; CGFloat y = 0; CGFloat wh = 74; CGFloat margin = (self.bounds.size.width - cols * wh) / (cols + 1); // 布局按钮(九宫格) for (int i = 0; i < 9; i++) { UIButton *btn = self.subviews[i]; col = i % cols; row = i / cols; x = margin + (margin + wh) * col; y = (margin + wh) * row; btn.frame = CGRectMake(x, y, wh, wh); } } @end
相关文章推荐
- 石头剪子布
- mysql中utf-default collation
- 互联网网间结算的全球趋势及启示
- LintCode : 第一个错误的代码版本
- 玩转树莓派:OpenHAB的入门(一)
- 多线程——线程范围内变量的共享
- javascript 开发调试的利器(二) 获取当前执行函数及函数名称
- 【Matlab编程】Matlab让电脑失而复得
- 多线程——线程范围内变量的共享
- java对象和json对象之间互相转换
- 大数加法
- 如何通过Openssl实现私有CA,并为HTTP服务提供TLS/SLL安全机制
- 如何知道mysql中sql语句索引是否生效
- 杭电1026——Ignatius and the Princess I(BFS)
- .net压缩图片质量(附demo)
- ssh访问流程
- 实现键盘弹出时,显示Emoji按钮的功能
- android APK加固篇-1. 动态加载的Dex文件的生成
- socket 的理解
- ViewPager实现导航