iOS开发-支付宝手势解锁实现展示

仿造支付宝写的一个手势解锁的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

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值