iOS--开发之手势解锁

首先,我们先分析功能的实现过程,首先我们需要先看大致的实现过程:
1.加载九宫格页面
2.实现按钮被点击及滑动过程中按钮状态的改变
3.实现滑动过程中的连线
4.绘制完毕后判定密码是否正确,
5.密码判定后实现跳转。
下面我们就来用代码实现上述五个过程。
1.加载九宫格界面
1.1九宫格内控件的分布 3*3 ,我们可以自定义view(包含3*3个按钮),添加到viewController上。

//添加view中子控件
-(void)awakeFromNib
{
// 创建按钮
for (int i=0; i<9; i++) {
self.LineColor=[UIColor blueColor];
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
btn.userInteractionEnabled=NO;
// 设置按钮属性
[btn setBackgroundImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];
[btn setBackgroundImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateHighlighted ];
[btn setBackgroundImage:[UIImage imageNamed:@"gesture_node_error"] forState:UIControlStateDisabled];
[self addSubview:btn];
}
}
//布局view子控件
-(void)layoutSubviews
{
[super layoutSubviews];
CGFloat width=74;
CGFloat height=74;
CGFloat Margin=(self.bounds.size.width-3*width)/2;
// 遍历设置9个button的frame
[self.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
// 通过tag设置按钮的索引标识
obj.tag=idx;
int row=(int)idx/3;
int col=idx%3;
obj.frame=CGRectMake(col*(Margin + width), row*(Margin +height), width, height);
}];
}

1.2将定义好的view通过xib添加到viewController上
首先,定义一个blockview(九宫格view)的类方法,
// 加载xib文件
+(instancetype)lockView
{
return [[[NSBundle mainBundle]loadNibNamed:@"MYblockView" owner:nil options:nil]lastObject];
}
然后加载到控制器上。

// 设置控制器view的背景图片
self.view.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:@"bg"]];
MYblockView *blockView=[MYblockView lockView];
blockView.center=self.view.center;
// 将blockview添加到viewController上
[self.view addSubview:blockView];

2.实现按钮被点击及滑动过程中按钮状态的改变
2.1定义数组类型的成员属性,用来装被点击的按钮

@property(nonatomic,strong)NSMutableArray *btnArr;
//懒加载
-(NSMutableArray *)btnArr
{
if (_btnArr==nil) {
_btnArr=[NSMutableArray array];
}
return _btnArr;
}

2.2创建路径,绘制图形

#pragma mark----绘制图形
-(void)drawRect:(CGRect)rect
{
if (self.btnArr.count==0 ) {
return;
}
// 创建路径
UIBezierPath *path=[UIBezierPath bezierPath];
// 遍历所有按钮进行绘制
[self.btnArr enumerateObjectsUsingBlock:^(__kindof UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
// 第一个按钮,中心点就是起点
if (idx==0) {
[path moveToPoint:obj.center];
}else
{
[path addLineToPoint:obj.center];
}
}];
[path addLineToPoint:self.currentPoint];
// 设置路径属性
path.lineWidth=10;
path.lineCapStyle=kCGLineCapRound;
path.lineJoinStyle=kCGLineJoinRound;
[self.LineColor setStroke];
// 渲染
[path stroke];
}

2.3开始触摸

#pragma mark-----开始触摸
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 获取触摸对象
UITouch *touch=touches.anyObject;
// 获取触摸点
CGPoint loc=[touch locationInView:self];
// 遍历按钮,判定触摸点是否在按钮上
[self.subviews enumerateObjectsUsingBlock:^(__kindof UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
BOOL isContains=CGRectContainsPoint(obj.frame, loc);
// 如果在按钮上,将当前按钮保存在数组中,并改变按钮状态
if (isContains&&obj.highlighted==NO) {
[self.btnArr addObject:obj];
obj.highlighted=YES;
}else
{
obj.highlighted=NO;
}
}];
}

2.4滑动过程中,重绘

#pragma mark----开始滑动
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 获取触摸对象
UITouch *touch=touches.anyObject;
// 获取触摸点
CGPoint loc=[touch locationInView:self];
self.currentPoint=loc;
// 遍历按钮,如果按钮在滑动路径上,就改变按钮状态
[self.subviews enumerateObjectsUsingBlock:^(__kindof UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
BOOL isContains=CGRectContainsPoint(obj.frame, loc);
if (isContains&&obj.highlighted==NO) {
[self.btnArr addObject:obj];
obj.highlighted=YES;
}
}];
// 重绘
[self setNeedsDisplay];
}

3.实现滑动过程中的连线和4.绘制完毕后判定密码是否正确,

#pragma mark----停止滑动结束
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 定义最后一个按钮
UIButton *lastBtn=[self.btnArr lastObject];
// 将最后一个按钮中心点定义为相对滑动的当前点
self.currentPoint=lastBtn.center;
// 重绘
[self setNeedsDisplay];
// 判定密码
self.password=[NSMutableString string];
[self.btnArr enumerateObjectsUsingBlock:^( UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[self.password appendFormat:@"%@",@(obj.tag)];
}];
NSLog(@"%@",self.password);
BOOL isOk;
if ([self.delegate respondsToSelector:@selector(blockView:finishedWithPassword:)]) {
isOk= [self.delegate blockView:self finishedWithPassword:self.password];
}
if (isOk) {
[self.btnArr enumerateObjectsUsingBlock:^(UIButton* _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
obj.highlighted=NO; }];
[self.btnArr removeAllObjects];
[self setNeedsDisplay]; NSLog(@"密码正确");
}else
{
NSLog(@"密码错误");
} }

注意:我们在密码判定过程中是通过根据先前布局按钮的时候定义的按钮tag值进行字符串拼接,密码传值是通过代理实现。

#import <UIKit/UIKit.h>
@class MYblockView;
//声明代理
@protocol MYblockViewDelegate <NSObject>
@optional
//代理方法
-(BOOL) blockView:(MYblockView *)blockView finishedWithPassword:(NSString *)password;
@end
@interface MYblockView : UIView
+(instancetype)lockView;
//设置代理成员属性
@property(nonatomic,weak)id<MYblockViewDelegate>delegate;
@end

5.密码判定后实现跳转。

else
{ // 关闭用户交互
self.userInteractionEnabled=NO;
[self.btnArr enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
self.LineColor=[UIColor redColor];
obj.highlighted=NO;
obj.enabled=NO;
[self setNeedsDisplay]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 回复按钮状态
[self.btnArr enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
obj.enabled=YES;
}];
// 恢复线条的颜色
self.LineColor=[UIColor blueColor]; [self.btnArr removeAllObjects]; [self setNeedsDisplay];
});
}];
NSLog(@"密码错误");
}
self.userInteractionEnabled=YES; }

代理判定密码并实现跳转

-(BOOL)blockView:(MYblockView *)blockView finishedWithPassword:(NSString *)password
{
if ([password isEqualToString:@"012"]) { UIViewController *two=[UIViewController new];
two.view.backgroundColor=[UIColor greenColor];
[self.navigationController pushViewController:two animated:YES];
return YES;
}
else{
return NO;
}
}

最后设置控制器navigationbar属性
[self.navigationController.navigationBar setBackgroundColor:[UIColor redColor]];
[ self.navigationController.navigationBar setTitleTextAttributes:@{
NSForegroundColorAttributeName :[UIColor whiteColor]
}];
iOS--开发之手势解锁的更多相关文章
- iOS开发-UITapGestureRecognizer手势
手势在iOS开发中是一个比较常用的功能,不过相对来说大家用的比较少,经常刷网易新闻,上次用了一下捏合手势才发现可以调整字体大小.昨天看到一个介绍摇一摇这个功能的,没看到之前一直都觉得摇一摇是微信的专有 ...
- iOS开发摇动手势实现详解
1.当设备摇动时,系统会算出加速计的值,并告知是否发生了摇动手势.系统只会运动开始和结束时通知你,并不会在运动发生的整个过程中始终向你报告每一次运动.例如,你快速摇动设备三次,那只会收到一个摇动事件. ...
- 【转】 iOS开发之手势gesture详解
原文:http://www.cnblogs.com/salam/archive/2013/04/30/iOS_gesture.html 前言 在iOS中,你可以使用系统内置的手势识别 (Gesture ...
- iOS开发之指纹解锁
http://blog.csdn.net/hongfengkt/article/details/49868073 前一阵子一直在赶项目进度,没有太多时间写博客,现在终于空闲了,将以前欠下的博客补上来. ...
- iOS开发之手势gesture详解(二)
与其他用户界面控件交互 UIControl子类会覆盖parentView的gesture.例如当用户点击UIButton时,UIButton会接受触摸事件,它的parentView不会接收到.这仅适用 ...
- iOS开发之手势gesture详解(一)
前言 在iOS中,你可以使用系统内置的手势识别(GestureRecognizer),也可以创建自己的手势.GestureRecognizer将低级别的转换为高级别的执行行为,是你绑定到view的对象 ...
- iOS开发 UIPanGestureRecognizer手势抽象类
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@sel ...
- iOS开发: 向右滑动手势功能实现
在navigationController中实现向右滑动 返回功能 系统提供的backbarbuttonitem,不用添加任何代码即可实现向右滑动后退功能,但是往往要对按钮修改样式等时,就需要自定义l ...
- ios开发之手势动作状态细分state,同一视图加入两个手势
1.比方拖拽一个视图.形成类似scrollView的翻页形式 在拖拽的方法里推断拖拽的状态state属性,依据状态不同运行自己须要的效果. 2.同一视图加入两个手势,须要使用手势的代理方法.同意此操作 ...
- ios开发之手势处理 之手势识别一
#import "ViewController.h" @interface ViewController ()<UIGestureRecognizerDelegate> ...
随机推荐
- 二叉平衡查找树AvlTree(C实现)
二叉平衡查找树即是一棵树中所有节点的左右子树高度差不超过1的查找树 头文件—————————————————————————————— #ifndef _AVLTREE_H_ #define _AVL ...
- 【.Net底层剖析】2.stfld指令-给对象的字段赋值
.Net底层剖析目录章节 1.[深入浅出.Net IL]1.一个For循环引发的IL 2.[.Net底层剖析]2.stfld指令-给对象的字段赋值 3.[.Net底层剖析]3.用IL来理解属性 引言: ...
- ruby -- 进阶学习(十一)配置解决production环境下无法加载css或js
最近配置production环境,找了好几份文档,从傻逼到苦逼~~终于配置成功~~@_@!!! 首先,先加载以下几个插件: # Use Uglifier as compressor for JavaS ...
- ruby -- 进阶学习(十二)fragment cache
基于rails4.0环境 Rails 页面缓存的方法很多,最近弱弱地尝试了fragment cache,用法还算简单~@_@|| 首先,查看config/environment/production. ...
- 使用TFS+GIT实现分布式项目管理
前言 GIT是近来很流行的一种版本控制系统,是Linux内核之父Linus Torvalds为了管理Linux内核的开发而开发的一种开源的版本控制工具. GIT相比传统的版本控制工具最大的优点是实现了 ...
- Java Annotation认知(包括框架图、详细介绍、示例说明)
摘要 Java Annotation是JDK5.0引入的一种注释机制. 网上很多关于Java Annotation的文章,看得人眼花缭乱.Java Annotation本来很简单的,结果说的人没说清楚 ...
- 使用自带的JavaScriptSerializer序列化实体 指定的属性如何不序列化
public class GridConfig { public string width = "100%"; public string source = "dataA ...
- ASP.NET 图片上传工具类 upload image简单好用功能齐全
使用方法: UploadImage ui = new UploadImage(); /***可选参数***/ ui.SetWordWater = "哈哈";//文字水印 // ui ...
- 《构建之法》第8、9、10章的读后感和第一个sprint总结
第八章——主要介绍软件需求. 主要步骤:1.获取和引导需求.2.分析和定义需求.3.验证需求.4.在软件产品的生命周期中管理需求. 对软件需求的划分:1.对产品功能性的需求.2.对产品开发过程的需求. ...
- Python 3.x自定义迭代器对象
Python 3.x与Python 2.x之间存在着较多的语法细节差异.今天在看Python核心编程的时候,说到了自定义迭代器对象.于是动手将源码打了一遍,原书代码如下: class AnyIter( ...