您的位置:首页 > 其它

Quartz 2D之手势解锁(支付宝)

2016-04-12 19:05 363 查看
仿造支付宝写的一个手势解锁的Demo,那么废话不多说直接上代码!





//

// ViewController.h

// Quartz 2D - 手势解锁

//

// Created by 周昭 on 16/4/12.

// Copyright © 2016年 Jordan Zhou. All rights reserved.

//

#import <UIKit/UIKit.h>

@interface ViewController :
UIViewController

@end

//

// ViewController.m

// Quartz 2D - 手势解锁

//

// Created by 周昭 on 16/4/12.

// Copyright © 2016年 Jordan Zhou. All rights reserved.

//

#import "ViewController.h"

#import "ZZLockView.h"

@interface
ViewController ()<ZZLockViewDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {

[super
viewDidLoad];

//
设置背景

[self
setUpBackImg];

//
添加lockView

[self
setUpLockView];

}

/**

* 设置背景

*/

- (void)setUpBackImg

{

UIImageView *bgImg = [[UIImageView
alloc]
initWithFrame:self.view.frame];

bgImg.image = [UIImage
imageNamed:@"Home_refresh_bg"];

[self.view
addSubview:bgImg];

}

/**

* 添加lockView

*/

- (void)setUpLockView

{

ZZLockView *lockView = [[ZZLockView
alloc] init];

lockView.delegate =
self;

lockView.backgroundColor = [UIColor
clearColor];

lockView.center =
CGPointMake(self.view.frame.size.width
* 0.5,
self.view.frame.size.height *
0.5);

lockView.bounds =
CGRectMake(0,
0, self.view.frame.size.width,
self.view.frame.size.height);

[self.view
addSubview:lockView];

}

/**

* 代理方法

*/

- (void)lockView:(ZZLockView *)lockView didFinishPath:(NSString *)path

{

NSLog(@"拿到我们的path进行操作进行对比");

}

@end

//

// ZZLockView.h

// Quartz 2D - 手势解锁

//

// Created by 周昭 on 16/4/12.

// Copyright © 2016年 Jordan Zhou. All rights reserved.

//

#import <UIKit/UIKit.h>

@class ZZLockView;

@protocol ZZLockViewDelegate <NSObject>

@optional

- (void)lockView:(ZZLockView *)lockView didFinishPath:(NSString *)path;

@end

@interface ZZLockView :
UIView

@property (nonatomic,
weak) id <ZZLockViewDelegate> delegate;

@end

//

// ZZLockView.m

// Quartz 2D - 手势解锁

//

// Created by 周昭 on 16/4/12.

// Copyright © 2016年 Jordan Zhou. All rights reserved.

//

#import "ZZLockView.h"

#import "ZZCircleBtn.h"

@interface ZZLockView()

@property (nonatomic,
strong) NSMutableArray *selectedButtons;

@property (nonatomic,
assign) CGPoint currentMovePoint;

@end

@implementation ZZLockView

- (NSMutableArray *)selectedButtons

{

if (!_selectedButtons) {

_selectedButtons = [NSMutableArray
array];

}

return
_selectedButtons;

}

/**

* 初始化

*/

- (instancetype)initWithFrame:(CGRect)frame

{

if (self = [super
initWithFrame:frame]) {

[self setUp];

}

return
self;

}

/**

* 无论你从什么创建Xib\代码创建都可以

*/

- (instancetype)initWithCoder:(NSCoder *)aDecoder

{

if (self = [super
initWithCoder:aDecoder]) {

[self setUp];

}

return
self;

}

/**

* 添加按钮

*/

- (void)setUp

{

for (int index =
0; index < 9; index++) {

#pragma mark --- 封装一层封装一层circleBtn

// 创建背景

ZZCircleBtn *btn = [ZZCircleBtn
buttonWithType:UIButtonTypeCustom];

// 绑定tag得到路径(所以这里我们在数组中存的直接是这个按钮\当然你存按钮的中点也是可以的但是路径呢?)

btn.tag = index;

// 添加按钮

[self addSubview:btn];

}

}

/**

* 已经添加那么在这里设置他的frame

*/

- (void)layoutSubviews

{

for (int index =
0; index < self.subviews.count; index++) {

// 取出按钮

ZZCircleBtn *btn =
self.subviews[index];

int totolColumns =
3;

int col = index % totolColumns;

int row = index / totolColumns;

CGFloat btnW =
74;

CGFloat btnH =
74;

CGFloat marginX = (self.frame.size.width - totolColumns * btnW) / (totolColumns
+ 1);

CGFloat marginY = marginX;

CGFloat btnX = marginX + col * (marginX + btnW);

CGFloat btnY = marginY + row * (marginY + btnH);

btn.frame =
CGRectMake(btnX, btnY, btnW, btnH);

}

}

#pragma mark ---- 私有方法

/**

* 根据touches的集合获得对应触摸点的位置

*/

- (CGPoint)pointWithTouches:(NSSet *)touches

{

// 1.取出按钮的点

UITouch *touch = [touches
anyObject];

return [touch
locationInView:touch.view];

}

/**

* 根据我们的触摸点判断是不是选中的按钮

*/

- (ZZCircleBtn *)buttonWithPoint:(CGPoint)point

{

//
遍历 CGRectContainsPoint(btn.frame, pos)
返回BOOL值
看这个点在不在这个范围内

for (ZZCircleBtn *btn
in self.subviews) {

#pragma mark ---- 判断到圆心的才连接

CGFloat wh =
24;

CGFloat frameX = btn.center.x - wh *
0.5;

CGFloat frameY = btn.center.y - wh *
0.5;

if (CGRectContainsPoint(CGRectMake(frameX, frameY, wh, wh), point)) {

return btn;

}

}

return
nil;

}

#pragma mark ---- 触摸方法

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{

// 0.我们一按下去就把这个点清空

self.currentMovePoint =
CGPointZero;

// 1.获得触摸点

CGPoint pos = [self
pointWithTouches:touches];

// 2.获得触摸的按钮

ZZCircleBtn *btn = [self
buttonWithPoint:pos];

if (btn && btn.selected ==
NO) {

// 3.按钮被选中

btn.selected =
YES;

// 4.添加到数组中(如果你直接这么写一看就没经验 [self.selectedButtons addObject:btn]; btn
可能为空
所有以后数组和字典中添加东西一定判断为不为空)

[self.selectedButtons
addObject:btn];

}

}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{

// 1.获得触摸点

CGPoint pos = [self
pointWithTouches:touches];

// 2.获得触摸的按钮

ZZCircleBtn *btn = [self
buttonWithPoint:pos];

if (btn && btn.selected ==
NO) {

// 3.按钮被选中

btn.selected =
YES;

// 4.添加到数组中(如果你直接这么写一看就没经验 [self.selectedButtons addObject:btn]; btn
可能为空
所有以后数组和字典中添加东西一定判断为不为空)

[self.selectedButtons
addObject:btn];

} else { //
没有摸到按钮

self.currentMovePoint = pos;

}

// 5.刷新

[self
setNeedsDisplay];

}

/**

* 触摸结束

*/

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{

if ([self.delegate
respondsToSelector:@selector(lockView:didFinishPath:)]) {

//
得到画的路径

NSMutableString *path = [NSMutableString
string];

for (ZZCircleBtn *btn
in self.selectedButtons) {

[path appendFormat:@"%ld",btn.tag];

}

NSLog(@"%@",path);

[self.delegate
lockView:self
didFinishPath:path];

}

// 取消选中的所有按钮\能尽量优化的时候就应该优化那么这里没必要遍历所有的子控件

for (ZZCircleBtn *btn
in self.selectedButtons) {

btn.selected =
NO;

}

// 让所有的按钮都执行这个方法 \
注意最后一个返回值一定要包装成对象就行

// [self.selectedButtons makeObjectsPerformSelector:@selector(setSelected:) withObject:@(NO)];

[self.selectedButtons
removeAllObjects];

[self
setNeedsDisplay];

}

/**

* 触摸被打破我们直接调用touchesEnded的方法

*/

- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{

[self touchesEnded:touches
withEvent:event];

}

#pragma mark --- 绘图

- (void)drawRect:(CGRect)rect

{

if (self.selectedButtons.count ==
0) return;

UIBezierPath *path = [UIBezierPath
bezierPath];

for (int index =
0; index < self.selectedButtons.count; index++) {

ZZCircleBtn *btn =
self.selectedButtons[index];

if (index ==
0) {

[path moveToPoint:btn.center];

} else {

[path addLineToPoint:btn.center];

}

}

// 如果当前点没有那么我们就要清除

if (CGPointEqualToPoint(self.currentMovePoint,
CGPointZero) ==
NO) {

[path addLineToPoint:self.currentMovePoint];

}

//
设置连接样式

path.lineJoinStyle =
kCGLineJoinBevel;

path.lineWidth =
10;

[[UIColor
colorWithRed:32/255.0
green:210/255.0
blue:254/255.0
alpha:0.7]
set];

[path stroke];

}

@end

//

// ZZCircleBtn.h

// Quartz 2D - 手势解锁

//

// Created by 周昭 on 16/4/12.

// Copyright © 2016年 Jordan Zhou. All rights reserved.

//

#import <UIKit/UIKit.h>

@interface ZZCircleBtn :
UIButton

@end

//

// ZZCircleBtn.m

// Quartz 2D - 手势解锁

//

// Created by 周昭 on 16/4/12.

// Copyright © 2016年 Jordan Zhou. All rights reserved.

//

#import "ZZCircleBtn.h"

@implementation ZZCircleBtn

/**

* 初始化

*/

- (instancetype)initWithFrame:(CGRect)frame

{

if (self = [super
initWithFrame:frame]) {

[self setUp];

}

return
self;

}

/**

* 无论你从什么创建Xib\代码创建都可以

*/

- (instancetype)initWithCoder:(NSCoder *)aDecoder

{

if (self = [super
initWithCoder:aDecoder]) {

[self setUp];

}

return
self;

}

/**

* 添加按钮

*/

- (void)setUp

{

// 直接让按钮不能响应事件否则按钮长按会变色

self.userInteractionEnabled =
NO;

// 设置默认按钮图片

[self
setBackgroundImage:[UIImage
imageNamed:@"gesture_node_normal"]
forState:UIControlStateNormal];

// 设置选中是按钮的图片(为什么是selected?当你的按钮离开的时候就不是highlighted所以要选中)

[self
setBackgroundImage:[UIImage
imageNamed:@"gesture_node_highlighted"]
forState:UIControlStateSelected];

}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: