zoukankan      html  css  js  c++  java
  • 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]    
                                                                         }];
  • 相关阅读:
    Golang基础笔记
    PHP面试题
    PHP操作文件常用函数
    转:C#委托与事件
    转:Tkinter教程之Text(2)篇
    Tkinter教程之Text篇(1)
    转:Python 从FTP 下载数据的例子
    转:Python模块学习 ---- httplib HTTP协议客户端实现
    转:Python yield 使用浅析
    有用的网址地址
  • 原文地址:https://www.cnblogs.com/bolin-123/p/5259935.html
Copyright © 2011-2022 走看看