iOS开发之手势解锁详解
2016-05-26 11:50
447 查看
A.需求
1.九宫格手势解锁
2.使用了绘图和手势事件
code source: https://github.com/hellovoidworld/GestureUnlockDemo
B.实现
使用按钮来处理每个圆点
使用代码生成按钮
取消按钮点击事件
设置普通状态和选中状态的背景图片
CGRectContainsPoint,移动到按钮范围内改变按钮为选中状态
按钮的连接:使用数组存储被选中的所有按钮,画上连线
已经连线的按钮不需要再连线
触摸结束清空连线和按钮选中状态
移动中也要画出线,最后的点用来辅助画移动中的线
解决bug:每次触摸开始重置当前画笔位置
设置触摸触发选中的按钮内部范围
使用tag记录按钮的选中顺序轨迹,触摸结束取得轨迹
封装整个手势解锁view成为一个自定义控件
封装按钮称为自定类
1.准备基础界面,使用一个UIView作为解锁画面
2.在控制器ViewController设置一下背景图片和状态栏
3.自定义解锁画面的类HVWLockView
4.使用代码初始化HVWLockView的子控件—按钮,设置按钮的样式、位置尺寸
out:
5.实现触摸事件方法
(1)点击开始,使被点击的按钮改变为选中状态(改变图片)
(2)点击拖曳中,同样使被触碰到的按钮改变为选中状态
(3)点击结束,清空选中状态
(4)小修改:把HVWLockView背景改为透明
HVWLockView:
UITouch
*touch
=
[touches
anyObject];
CGPoint
touchLocation =
[touch
locationInView:touch.view];
//
检测哪个按钮被点中了
for
(HVWLockButton
*button
in
self.subviews)
{
if
(CGRectContainsPoint(button.frame,
touchLocation))
{
button.selected
=
YES;
}
}
}
-
(void)touchesMoved:(NSSet
*)touches
withEvent:(UIEvent
*)event
{
UITouch
*touch
=
[touches
anyObject];
CGPoint
touchLocation =
[touch
locationInView:touch.view];
//
检测哪个按钮被点中了
for
(HVWLockButton
*button
in
self.subviews)
{
if
(CGRectContainsPoint(button.frame,
touchLocation))
{
button.selected
=
YES;
}
}
}
-
(void)
touchesEnded:(NSSet
*)touches
withEvent:(UIEvent
*)event
{
//
消除所有按钮选中状态
for
(HVWLockButton
*button
in
self.subviews)
{
button.selected
=
NO;
}
}
out:
6.画出连接线
(1)优化:将按钮封装为一个类HVWLockButton
(2)使用一个数组来存储已经被选择的按钮
(3)把触碰到的按钮到加入到上述数组中
(4)在绘图方法中把数组内的按钮用线连起来
(5)使用一个成员变量来存储当前触摸位置,画出最后触摸的按钮到现触摸点的线
(6)重复触碰同一个按钮的时候,不用重绘和计算
(7)创建一个代理方法,在触摸结束的时候输出轨迹序列
(8)精简一下代码
out:
2015-01-12 16:39:23.794 HVWLockView[10274:184387] 手势解锁的输出序列:01246
1.九宫格手势解锁
2.使用了绘图和手势事件
code source: https://github.com/hellovoidworld/GestureUnlockDemo
B.实现
使用按钮来处理每个圆点
使用代码生成按钮
取消按钮点击事件
设置普通状态和选中状态的背景图片
CGRectContainsPoint,移动到按钮范围内改变按钮为选中状态
按钮的连接:使用数组存储被选中的所有按钮,画上连线
已经连线的按钮不需要再连线
触摸结束清空连线和按钮选中状态
移动中也要画出线,最后的点用来辅助画移动中的线
解决bug:每次触摸开始重置当前画笔位置
设置触摸触发选中的按钮内部范围
使用tag记录按钮的选中顺序轨迹,触摸结束取得轨迹
封装整个手势解锁view成为一个自定义控件
封装按钮称为自定类
1.准备基础界面,使用一个UIView作为解锁画面
2.在控制器ViewController设置一下背景图片和状态栏
// // ViewController.m // HVWLockView // // Created by hellovoidworld on 15/1/12. // Copyright (c) 2015年 hellovoidworld. All rights reserved. // #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 设置背景 self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"Home_refresh_bg"]]; } /** 设置状态栏样式 */ - (UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
3.自定义解锁画面的类HVWLockView
4.使用代码初始化HVWLockView的子控件—按钮,设置按钮的样式、位置尺寸
// // HVWLockView.m // HVWLockView // // Created by hellovoidworld on 15/1/12. // Copyright (c) 2015年 hellovoidworld. All rights reserved. // #import "HVWLockView.h" #import "HVWLockButton.h" #define BUTTON_COUNT 9 #define BUTTON_COL_COUNT 3 @implementation HVWLockView #pragma mark - 初始化方法 /** 使用文件初始化 */ - (id)initWithCoder:(NSCoder *)aDecoder { if (self = [super initWithCoder:aDecoder]) { [self initView]; } return self; } /** 使用代码初始化 */ - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { [self initView]; } return self; } /** 初始化view内的控件(按钮) */ - (void) initView { for (int i=0; i<BUTTON_COUNT; i++) { HVWLockButton *button = [HVWLockButton buttonWithType:UIButtonTypeCustom]; // 取消点击时间 button.userInteractionEnabled = NO; // 设置指标tag,用来记录轨迹 button.tag = i; // 设置普通状态图片 [button setBackgroundImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal]; // 设置选中状态图片 [button setBackgroundImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected]; // 加入按钮到lock view [self addSubview:button]; } } /** 设置按钮位置尺寸 */ - (void)layoutSubviews { [super layoutSubviews]; // 取出所有按钮 for (int i=0; i<self.subviews.count; i++) { HVWLockButton *button = self.subviews[i]; CGFloat buttonWidth = 74; CGFloat buttonHeight = 74; // 此按钮所在列号 int col = i % BUTTON_COL_COUNT; // 此按钮所在行号 int row = i / BUTTON_COL_COUNT; // 等分水平多余空间,计算出间隙 CGFloat marginX = (self.frame.size.width - BUTTON_COL_COUNT * buttonWidth) / (BUTTON_COL_COUNT + 1); CGFloat marginY = marginX; // x坐标 CGFloat buttonX = marginX + col * (buttonWidth + marginX); // y坐标 CGFloat buttonY = marginY + row * (buttonHeight + marginY); button.frame = CGRectMake(buttonX, buttonY, buttonWidth, buttonHeight); } } @end
out:
5.实现触摸事件方法
(1)点击开始,使被点击的按钮改变为选中状态(改变图片)
(2)点击拖曳中,同样使被触碰到的按钮改变为选中状态
(3)点击结束,清空选中状态
(4)小修改:把HVWLockView背景改为透明
HVWLockView:
UITouch
*touch
=
[touches
anyObject];
CGPoint
touchLocation =
[touch
locationInView:touch.view];
//
检测哪个按钮被点中了
for
(HVWLockButton
*button
in
self.subviews)
{
if
(CGRectContainsPoint(button.frame,
touchLocation))
{
button.selected
=
YES;
}
}
}
-
(void)touchesMoved:(NSSet
*)touches
withEvent:(UIEvent
*)event
{
UITouch
*touch
=
[touches
anyObject];
CGPoint
touchLocation =
[touch
locationInView:touch.view];
//
检测哪个按钮被点中了
for
(HVWLockButton
*button
in
self.subviews)
{
if
(CGRectContainsPoint(button.frame,
touchLocation))
{
button.selected
=
YES;
}
}
}
-
(void)
touchesEnded:(NSSet
*)touches
withEvent:(UIEvent
*)event
{
//
消除所有按钮选中状态
for
(HVWLockButton
*button
in
self.subviews)
{
button.selected
=
NO;
}
}
out:
6.画出连接线
(1)优化:将按钮封装为一个类HVWLockButton
// // HVWLockButton.m // HVWLockView // // Created by hellovoidworld on 15/1/12. // Copyright (c) 2015年 hellovoidworld. All rights reserved. // #import "HVWLockButton.h" @implementation HVWLockButton /** 使用文件创建会调用 */ - (id)initWithCoder:(NSCoder *)aDecoder { if (self = [super initWithCoder:aDecoder]) { [self initLockButton]; } return self; } /** 使用代码创建会调用 */ - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { [self initLockButton]; } return self; } /** 初始化 */ - (void) initLockButton { // 取消交互事件(点击) self.userInteractionEnabled = NO; // 设置普通状态图片 [self setBackgroundImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal]; // 设置选中状态图片 [self setBackgroundImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected]; } @end
(2)使用一个数组来存储已经被选择的按钮
(3)把触碰到的按钮到加入到上述数组中
(4)在绘图方法中把数组内的按钮用线连起来
(5)使用一个成员变量来存储当前触摸位置,画出最后触摸的按钮到现触摸点的线
(6)重复触碰同一个按钮的时候,不用重绘和计算
(7)创建一个代理方法,在触摸结束的时候输出轨迹序列
(8)精简一下代码
#define BUTTON_COUNT 9 #define BUTTON_COL_COUNT 3 @interface HVWLockView() /** 已选择按钮数组 */ @property(nonatomic, strong) NSMutableArray *selectedButtons; /** 触摸位置 */ @property(nonatomic, assign) CGPoint currentTouchLocation; @end @implementation HVWLockView /** 初始化数组 */ - (NSMutableArray *)selectedButtons { if (nil == _selectedButtons) { _selectedButtons = [NSMutableArray array]; } return _selectedButtons; } #pragma mark - 初始化方法 /** 使用文件初始化 */ - (id)initWithCoder:(NSCoder *)aDecoder { if (self = [super initWithCoder:aDecoder]) { [self initView]; } return self; } /** 使用代码初始化 */ - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { [self initView]; } return self; } /** 初始化view内的控件(按钮) */ - (void) initView { // 设置透明背景 self.backgroundColor = [[UIColor alloc] initWithRed:1 green:1 blue:1 alpha:0]; for (int i=0; i<BUTTON_COUNT; i++) { HVWLockButton *button = [HVWLockButton buttonWithType:UIButtonTypeCustom]; // 设置指标tag,用来记录轨迹 button.tag = i; // 加入按钮到lock view [self addSubview:button]; } } /** 设置按钮位置尺寸 */ - (void)layoutSubviews { [super layoutSubviews]; // 取出所有按钮 for (int i=0; i<self.subviews.count; i++) { HVWLockButton *button = self.subviews[i]; CGFloat buttonWidth = 74; CGFloat buttonHeight = 74; // 此按钮所在列号 int col = i % BUTTON_COL_COUNT; // 此按钮所在行号 int row = i / BUTTON_COL_COUNT; // 等分水平多余空间,计算出间隙 CGFloat marginX = (self.frame.size.width - BUTTON_COL_COUNT * buttonWidth) / (BUTTON_COL_COUNT + 1); CGFloat marginY = marginX; // x坐标 CGFloat buttonX = marginX + col * (buttonWidth + marginX); // y坐标 CGFloat buttonY = marginY + row * (buttonHeight + marginY); button.frame = CGRectMake(buttonX, buttonY, buttonWidth, buttonHeight); } } #pragma mark - 触摸事件 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self touchesMoved:touches withEvent:event]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint touchLocation = [touch locationInView:touch.view]; // 检测哪个按钮被点中了 for (HVWLockButton *button in self.subviews) { // 如果触碰到了此按钮 if (CGRectContainsPoint(button.touchFrame, touchLocation)) { button.selected = YES; // 如果此按钮没有被触碰过才进行处理 if (![self.selectedButtons containsObject:button]) { // 加入到数组 [self.selectedButtons addObject:button]; } } // 当前触摸位置 self.currentTouchLocation = touchLocation; } // 重绘 [self setNeedsDisplay]; } - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { // 轨迹序列 NSMutableString *passPath = [NSMutableString string]; // 合成轨迹序列 for (HVWLockButton *button in self.selectedButtons) { // 添加到轨迹序列 [passPath appendFormat:@"%d", button.tag]; } // 调用代理方法 if ([self.delegate respondsToSelector:@selector(hvwLockView:didFinishedWithPath:)]) { [self.delegate hvwLockView:self didFinishedWithPath:passPath]; } // 清除选中状态 [self.selectedButtons makeObjectsPerformSelector:@selector(setSelected:) withObject:@(NO)]; // 清空数组 [self.selectedButtons removeAllObjects]; // 重绘 [self setNeedsDisplay]; } #pragma mark - 绘图方法 - (void)drawRect:(CGRect)rect { UIBezierPath *path = [UIBezierPath bezierPath]; // 遍历已选择按钮数组 for (int i=0; i<self.selectedButtons.count; i++) { HVWLockButton *button = self.selectedButtons[i]; if (0 == i) { [path moveToPoint:button.center]; } else { [path addLineToPoint:button.center]; } } if (self.selectedButtons.count) { [path addLineToPoint:self.currentTouchLocation]; } // 设置画笔 [[UIColor redColor] set]; [path setLineWidth:10]; [path setLineCapStyle:kCGLineCapRound]; [path setLineJoinStyle:kCGLineJoinBevel]; [path stroke]; } @end
out:
2015-01-12 16:39:23.794 HVWLockView[10274:184387] 手势解锁的输出序列:01246
相关文章推荐
- iOS CoreAnimation 关键帧动画 CAKeyframeAnimation
- iOS开发之深复制浅复制
- iOS推送的众多坑
- iOS-本地通知
- iOS系统自带分享功能
- iOS推送的众多坑
- iOS开发——keychain的使用
- iOS开发之计时器
- iOS 极光推送
- 利用anchorPoint和position实现缩放
- IOS 使用容联视频时隐藏本地视频,不让对方看到自己
- iOS 静态库,动态库与 Framework 浅析
- iOS开发之获取运营商和WIFI
- iOS制作演示gif
- iOS配置SSO授权
- 关于10.11不能安装CocoaPods的问题
- iOS 分享功能开发
- iOS开发之获取手机型号
- iOS或去平米分辨率 以及放大模式、高清模式
- iOS开发之获取本地沙盒等基本路径