你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS編程技術 >> iOS開發之手勢解鎖

iOS開發之手勢解鎖

編輯: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]    
                                                                     }];
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved