//
// Created by wangtouwang on 15/4/7.
// Copyright (c) 2015年 wangtouwang. All rights reserved.
// #import <UIKit/UIKit.h> @class YYLockView;
@protocol YYLockViewDelegate <NSObject>
//自定义一个协议
//协议方法,把当前视图作为参数
-(void)LockViewDidClick:(YYLockView *)lockView andPwd:(NSString *)pwd;
@end @interface YYLockView : UIView //代理
@property(nonatomic,weak) IBOutlet id<YYLockViewDelegate>delegate; @end
//
// YYLockView.m
// Created by wangtouwang on 15/4/7.
// Copyright (c) 2015年 wangtouwang. All rights reserved.
// #import "YYLockView.h"
// 设置获取屏幕长宽全局变量
#define KSCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define KSCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
#define BUTTON_HEIGHT_MIDDLE_WIDTH_RADIO 1.22 @interface YYLockView ()
{
UIView *newView;
}
@property(nonatomic,strong)NSMutableArray *buttons;
@property(nonatomic,strong)NSMutableArray *includButtons; //定义一个属性,记录当前点
@property(nonatomic,assign)CGPoint currentPoint; @end @implementation YYLockView #pragma mark-懒加载
-(NSMutableArray *)buttons
{
if (_buttons==nil) {
_buttons=[NSMutableArray array];
}
return _buttons;
} #pragma mark-懒加载
-(NSMutableArray *)includButtons
{
if (_includButtons==nil) {
_includButtons=[NSMutableArray array];
}
return _includButtons;
} -(id)initWithCoder:(NSCoder *)aDecoder
{
NSLog(@"断点 B 号 ");
if (self=[super initWithCoder:aDecoder]) {
[self setup];
}
return self;
} //界面搭建
- (id)initWithFrame:(CGRect)frame
{
NSLog(@"断点 1 号 ");
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
} //在界面上创建9个按钮
-(void)setup
{
// NSLog(@"断点 2 号 ");
// newView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
// newView.backgroundColor=[UIColor redColor];
// [self addSubview:newView];
//1.创建9个按钮
for (int i=; i<; i++) {
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
//2.设置按钮的状态背景
[btn setBackgroundImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];
[btn setBackgroundImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected];
//3.把按钮添加到视图中
[self addSubview:btn];
//将按钮添加到包含按钮数组中
[[self includButtons] addObject:btn];
//4.禁止按钮的点击事件
btn.userInteractionEnabled=NO;
//5.设置每个按钮的tag
btn.tag=i+;
}
} //4.设置按钮的frame
-(void)layoutSubviews
{
NSLog(@"断点顺序 3 号 ");
CGFloat inverst = KSCREEN_HEIGHT/4.5;
inverst=;
//4.1需要先调用父类的方法
[super layoutSubviews]; for (int i=; i<[self includButtons].count; i++) {
//4.2取出按钮
UIButton *btn=[self includButtons][i];
//4.3九宫格法计算每个按钮的frame
CGFloat row = i/;
CGFloat loc = i%;
// NSLog(@"ROW=%f LOC=%f",row,loc);
CGFloat btnW=;
CGFloat btnH=;
CGFloat padding=(self.frame.size.width-*btnW)/;
CGFloat btnX=padding+(btnW+padding)*loc;
CGFloat btnY=padding*BUTTON_HEIGHT_MIDDLE_WIDTH_RADIO+(btnW+padding)*row;
// NSLog(@"BTNX-%f BTNY=%f ",btnX,btnY);
btn.frame=CGRectMake(btnX, btnY+inverst, btnW, btnH);
}
} //重写drawrect:方法
-(void)drawRect:(CGRect)rect
{
NSLog(@"断点顺序 4 号 "); //获取上下文
CGContextRef ctx=UIGraphicsGetCurrentContext(); //在每次绘制前,清空上下文
CGContextClearRect(ctx, rect); //填充画布颜色
[[self renderImageWithColor:[UIColor grayColor] inSize:CGSizeMake(KSCREEN_WIDTH, KSCREEN_HEIGHT)] drawInRect:CGRectMake(, , KSCREEN_WIDTH, KSCREEN_HEIGHT)];//在坐标中画出图片 //绘图(线段)
for (int i=; i<self.buttons.count; i++) {
UIButton *btn=self.buttons[i];
if (==i) {
//设置起点(注意连接的是中点)
// CGContextMoveToPoint(ctx, btn.frame.origin.x, btn.frame.origin.y);
CGContextMoveToPoint(ctx, btn.center.x, btn.center.y);
}else
{
// CGContextAddLineToPoint(ctx, btn.frame.origin.x, btn.frame.origin.y);
CGContextAddLineToPoint(ctx, btn.center.x, btn.center.y);
}
} //当所有按钮的中点都连接好之后,再连接手指当前的位置
//判断数组中是否有按钮,只有有按钮的时候才绘制
if (self.buttons.count !=) {
CGContextAddLineToPoint(ctx, self.currentPoint.x, self.currentPoint.y);
} //渲染
//设置线条的属性
CGContextSetLineWidth(ctx, );
CGContextSetLineJoin(ctx, kCGLineJoinRound);
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetRGBStrokeColor(ctx, /255.0, /255.0, /255.0, ); CGContextStrokePath(ctx); } //填充画布颜色
- (UIImage *)renderImageWithColor:(UIColor *)color inSize:(CGSize)size
{
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect); UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext(); return image;
} //5.监听手指的移动
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"断点 E 号 ");
CGPoint starPoint=[self getCurrentPoint:touches];
UIButton *btn=[self getCurrentBtnWithPoint:starPoint]; if (btn && btn.selected != YES) {
btn.selected=YES;
[self.buttons addObject:btn];
}
// [self setNeedsDisplay];
} -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"断点 F 号 ");
CGPoint movePoint=[self getCurrentPoint:touches];
UIButton *btn=[self getCurrentBtnWithPoint:movePoint];
//存储按钮
//已经连过的按钮,不可再连
if (btn && btn.selected != YES) {
//设置按钮的选中状态
btn.selected=YES;
//把按钮添加到数组中
[self.buttons addObject:btn];
}
//记录当前点(不在按钮的范围内)
self.currentPoint=movePoint;
//通知view重新绘制
[self setNeedsDisplay];
} //手指离开的时候清除线条
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"断点 G 号 ");
//取出用户输入的密码
//创建一个可变的字符串,用来保存用户密码
NSMutableString *result=[NSMutableString string];
for (UIButton *btn in self.buttons) {
[result appendFormat:@"%lu",btn.tag];
}
NSLog(@"用户输入的密码为:%@",result);
//通知代理,告知用户输入的密码
if ([self.delegate respondsToSelector:@selector(LockViewDidClick:andPwd:)]) {
[self.delegate LockViewDidClick:self andPwd:result];
} //重置按钮的状态
// for (UIButton *btn in self.buttons) {
// btn.selected=NO;
//// [btn setSelected:NO];
// } //调用该方法,它就会让数组中的每一个元素都调用setSelected:方法,并给每一个元素传递一个NO参数
[self.buttons makeObjectsPerformSelector:@selector(setSelected:) withObject:@(NO)];
//清空数组
[self.buttons removeAllObjects];
[self setNeedsDisplay]; //清空当前点
self.currentPoint=CGPointZero;
} //对功能点进行封装
-(CGPoint)getCurrentPoint:(NSSet *)touches
{
NSLog(@"断点 H 号 ");
UITouch *touch=[touches anyObject];
CGPoint point=[touch locationInView:touch.view];
return point;
}
-(UIButton *)getCurrentBtnWithPoint:(CGPoint)point
{
NSLog(@"断点 J 号 ");
for (int i=;i<_includButtons.count;i++) {
UIButton *btn =_includButtons[i];
if (CGRectContainsPoint(btn.frame, point)) {
return btn;
}
}
return Nil;
} @end
 

(转 部分修改) IOS 手势密码(简单版)的更多相关文章

  1. swift 实现iOS手势密码、指纹密码、faceID

    本博客包含了如何实现iOS手势密码.指纹密码.faceID全步骤,包括了完整的代码. 先附上demo地址https://github.com/Liuyubao/LYBTouchID,支持swift3. ...

  2. 28.【转载】挖洞技巧:APP手势密码绕过思路总结

    说到APP手势密码绕过的问题,大家可能有些从来没接触过,或者接触过,但是思路也就停留在那几个点上,这里我总结了我这1年来白帽子生涯当中所挖掘的关于这方面的思路,有些是网上已经有的,有些是我自己不断摸索 ...

  3. APP手势密码绕过

    之前写的文章收到了很多的好评,主要就是帮助到了大家学习到了新的思路.自从发布了第一篇文章,我就开始筹备第二篇文章了,最终打算在07v8首发,这篇文章我可以保障大家能够学习到很多思路.之前想准备例子视频 ...

  4. iOS 九宫格手势密码

    代码地址如下:http://www.demodashi.com/demo/11490.html 一.准备工作 需要准备什么环境 xcode,iOS8+ 本例子实现什么功能 主要实现手势密码设置,验证 ...

  5. 下载文件时-修改文件名字 Redis在Windows中安装方法 SVN安装和使用(简单版) WinForm-SQL查询避免UI卡死 Asp.Net MVC Https设置

    下载文件时-修改文件名字   1后台代码 /// <summary> /// 文件下载2 /// </summary> /// <param name="Fil ...

  6. iOS 教你如何实现手势密码

    本次讲的手势密码,是在九个按键上实现的,这里讲的是手势密码的基本实现和效果 同样先上效果图 其实就是对画图功能的一个实现,再加上手势操作结合起来 屏幕宽度高度,方便下面操作,不做解释 #define ...

  7. 手把手教你修改iOS版QQ的运动步数

    手把手教你修改iOS版QQ的运动步数 现在很多软件都加上了运动模块,比如QQ和微信,而且还有排行榜,可以和好友比较谁的运动步数多,任何东西只要添加了比较功能,就变得不一样了.今天教大家用代码去修改QQ ...

  8. IOS 学习笔记 2015-04-15 手势密码(原)

    // // WPSignPasswordView.h // 网投网 // // Created by wangtouwang on 15/4/9. // Copyright (c) 2015年 wan ...

  9. 精通iOS开发(第5版)

    <精通iOS开发(第5版)> 基本信息 原书名:Beginning ios 6 development:exploring the ios sdk 作者: (美)David Mark   ...

随机推荐

  1. poj1515--Street Directions(边的双连通)

    给一个无向图,要求变成强连通的有向图,需要保留哪些边. 边的双连通,对于桥保留两条边,其他的只保留一条边.求双连通的过程中记录保留边. /******************************* ...

  2. 如何解决Python脚本在Linux和Windows上的格式问题

    python是一种对缩进有严格要求的语言, Python脚本可以使用非常多的工具进行编写,笔者在Linux系统使用JEdit进行Python脚本编写,由于在Linux编写脚本比较痛苦,比如想一眼看出相 ...

  3. Google正确搜索方法

    以下是目前所有的Google搜索命令语法,它不同于Google的帮助文档,因为这里介绍了几个Google不推荐使用的命令语法.大多数的Google搜索命令语法有它特有的使用格式,希望大家能正确使用.我 ...

  4. 在COM接口中不要使用同时出现只是大小写不同的名字作为属性名、函数名或者参数名

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:在COM接口中不要使用同时出现只是大小写不同的名字作为属性名.函数名或者参数名.

  5. ZooKeeper场景实践:(6)集群监控和Master选举

    1. 集群机器监控 这通经常使用于那种对集群中机器状态,机器在线率有较高要求的场景,可以高速对集群中机器变化作出响应.这种场景中,往往有一个监控系统,实时检測集群机器是否存活. 利用ZooKeeper ...

  6. native为本地方法

    在java中,native方法是指本地方法,当在方法中调用一些不是由java语言写的代码或者在方法中用java语言直接操纵计算机硬件时要声明为native方法. native方法的执行依赖于JVM的设 ...

  7. Linux内核里的DebugFS

    DebugFS,顾名思义,是一种用于内核调试的虚拟文件系统,内核开发者通过debugfs和用户空间交换数据.类似的虚拟文件系统还有procfs和sysfs等,这几种虚拟文件系统都并不实际存储在硬盘上, ...

  8. 最简便的MySql数据库备份方法

    http://www.kankanews.com/ICkengine/archives/194.shtml 使用MYSQL进行数据库备份,又很正规的数据库备份方法,同其他的数据库服务器有相同的概念,但 ...

  9. Java内存模型浅析

    JVM在执行java程序时会将它所管理的内存划分成若干个不同的数据区域.如图所示: 其中方法区和堆是所有线程共享的数据区,其他区域则是线程隔离的数据区. 这些区域的功能各有不同: 程序计数器:可以理解 ...

  10. 理解Objective-c中的copy

    说一下深拷贝和浅拷贝的基本概念:a指针指向地址A1, 浅拷贝是创建了一个b指针指向地址A1:深拷贝是创建了一个c指针指向地址A2,A1和A2的地址不同. 我们看到NSObject接口里面是已经声明了c ...