iOS开发 - 手势解锁的简单实现

#import "GestureView.h"
#define BUTTON_COUNT 9

@interface GestureView()

@property (nonatomic,strong) NSMutableArray *btns;
@property (nonatomic,strong) NSMutableArray *lineBtns;//存放需要连线的btn
@property (nonatomic,assign) CGPoint currentPoint;//手指最新的位置

@end

@implementation GestureView

-(NSMutableArray *)lineBtns
{
    if (!_lineBtns) {
        _lineBtns = [NSMutableArray array];
    }
    return _lineBtns;
}
-(NSMutableArray *)btns
{
    if (!_btns) {
        _btns = [NSMutableArray array];
        
        for (int  i = 0; i < BUTTON_COUNT; i ++)
        {
            UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
            
            //设置tag 生成密码
            btn.tag = i;
            
            //关闭用户的交互
            btn.userInteractionEnabled = NO;
            //设置默认的图片样式
            [btn setBackgroundImage:[UIImage imageNamed:@""] forState:UIControlStateNormal];
            //设置高亮图片样式
            [btn setBackgroundImage:[UIImage imageNamed:@""] forState:UIControlStateHighlighted];
            //设置密码错误的图片样式
            [btn setBackgroundImage:[UIImage imageNamed:@""] forState:UIControlStateSelected];
            
            [self addSubview:btn];
            
            [self.btns addObject:btn];
        }
    }
    return _btns;
}
//点击这个view的时候调用
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //获取触摸对象
    UITouch *t = touches.anyObject;
    //获取当前手势的位置
    CGPoint p = [t locationInView:t.view];
    
    for (int i = 0; i < self.btns.count; i ++)
    {
        //获取 btn
        UIButton *btn = self.btns[i];
        //判断手指的位置是不是在btn.frame的范围内
        if (CGRectContainsPoint(btn.frame, p))
        {
            //如果是 设置这个按钮的高亮状态
            btn.highlighted = YES;
            //判断 当前的btn 是不是已经存在于需要划线的数组
            if (![self.lineBtns containsObject:btn])
            {
                //如果不存在 再添加
                //因为变成高亮 所以需要划线
                [self.lineBtns addObject:btn];
            }
        }
    }
}
//在这个view上移动的时候调用
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //获取触摸对象
    UITouch *t = touches.anyObject;
    //获取当前手势的位置
    CGPoint p = [t locationInView:t.view];
    
    //把最新的手指的位置 赋值给全局 属性 用来最后的连线
    self.currentPoint = p;
    
    for (int i = 0; i < self.btns.count; i ++)
    {
        //获取 btn
        UIButton *btn = self.btns[i];
        //判断手指的位置是不是在btn.frame的范围内
        if (CGRectContainsPoint(btn.frame, p))
        {
            //如果是 设置这个按钮的高亮状态
            btn.highlighted = YES;
            //判断 当前的btn 是不是已经存在于需要划线的数组
            if (![self.lineBtns containsObject:btn])
            {
                //如果不存在 再添加
                //因为变成高亮 所以需要划线
                [self.lineBtns addObject:btn];
            }
        }
    }
    
    //重绘
    [self setNeedsDisplay];
}
//离开这个view的时候调用
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 把当前点的位置 修改为 画线数组的最后一个按钮的center
    self.currentPoint = [[self.lineBtns lastObject] center];
    //重绘
    [self setNeedsDisplay];
    //生成密码
    NSString *pwd = @"";
    
    //让所有需要连线的按钮都变成错误的样式 (变成选中状态)
    for (int i = 0; i < self.lineBtns.count; i ++)
    {
        //获取btn
        UIButton *btn = self.lineBtns[i];
        btn.selected = YES;
        btn.highlighted = NO;
        // 密码
        pwd = [pwd stringByAppendingString:[NSString stringWithFormat:@"%ld",btn.tag]];
    }
    
    //取消用户交互  解决错误以后还可以编辑的错误
    self.userInteractionEnabled = NO;
    
    //延时 取消
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //恢复到初试状态
        [self clear];
        //开启用户交互
        self.userInteractionEnabled = YES;
    });
}
//恢复到初试状态
- (void)clear
{
    for (int i = 0; i < self.btns.count; i ++)
    {
        //获取btn
        UIButton *btn = self.btns[i];
        btn.highlighted = NO;
        btn.selected = NO;
    }
    
    //清空所有的划线数组
    [self.lineBtns removeAllObjects];
    //重绘
    [self setNeedsDisplay];
}
//划线
- (void)drawRect:(CGRect)rect
{
    //创建一个路径
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    for (int i = 0; i < self.lineBtns.count; i ++)
    {
        //获取btn
        UIButton *btn = self.lineBtns[i];
        
        if (i == 0){//如果 i== 0 设置初始位置
            [path moveToPoint:btn.center];
        }else{//如果 i!=0 连线
            [path addLineToPoint:btn.center];
        }
    }
    
    //判断 数组是不是有元素 如果有 再去连线到手指的位置
    if (self.lineBtns.count)
    {
        //往手指的位置 连线
        [path addLineToPoint:self.currentPoint];
    }
    
    //设置样式
    [[UIColor colorWithRed:0 green:170/255.0 blue:1 alpha:1] set];
    [path setLineWidth:2];
    [path setLineCapStyle:kCGLineCapRound];
    [path setLineJoinStyle:kCGLineJoinRound];
    //渲染
    [path stroke];
}
//计算九宫格布局
-(void)layoutSubviews
{
    [super layoutSubviews];
    for (int i = 0; i < self.btns.count; i ++)
    {
        //计算九宫格位置
        CGFloat w = 74;
        CGFloat h = w;
        int colCount = 3;
        CGFloat margin = (self.frame.size.width - 3 * w) / 4;
        for (int i = 0; i < self.btns.count; i ++)
        {
            CGFloat x = (i % colCount) * (margin + w) + margin;
            CGFloat y = (i / colCount) * (margin + w) + margin;
            [self.btns[i] setFrame:CGRectMake(x, y, w, h)];
        }
    }
}

@end

 

转载于:https://my.oschina.net/gwlCode/blog/808379

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值