iOS手勢密碼鎖

原理非常簡單,做了初步的設計,詳細要求可根據個人要求進行更改 先將程式碼寫入文章中,之後程式會上傳上去;文中紅色部分為注意部分

1、首先建立一個工程

2、在main.storyboard新增一張背景圖片,之後新增一個UIView控制元件(名稱:SZLockView)

3、建立lockView檔案,關聯到main.storyboard中的view

4.在SZLockView程式碼如下

SZLockView.h中

#import <UIKit/UIKit.h>
@class SZLockView;
@protocol SZLockViewDelegate <NSObject>

-(void)lockView:(SZLockView *)lockView didFinishPath:(NSString *)path;
@end
@interface SZLockView : UIView
@property(nonatomic,assign)IBOutlet id <SZLockViewDelegate> delegate;
@end

SZLockView.m中

#import “SZLockView.h”
//const 定義只讀的變數名,在其他的類中不能宣告同樣的變數名
CGFloat const btnCount = 9;
CGFloat const btnW = 74;
CGFloat const btnH =74;
CGFloat const viewY = 200;
int const columnCount = 3;
#define SZSreenWidth [UIScreen mainScreen].bounds.size.width
@interface SZLockView()
//選擇的按鈕
@property(nonatomic,strong)NSMutableArray *selectedBtns;
//當前點
@property(nonatomic,assign)CGPoint currentPoint;
@end
@implementation SZLockView

-(NSMutableArray *)selectedBtns
{
    if (_selectedBtns == nil) {
        _selectedBtns = [NSMutableArray array];
    }
    return _selectedBtns;
}
//使用程式碼建立呼叫方法
-(instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        [self addButton];
    }
    return self;
}
//使用xib和storyboard建立代用方法
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super initWithCoder:aDecoder]) {
        [self addButton];
    }
    return self;
}
-(void)addButton
{
    CGFloat height = 0;
    for (int i = 0; i < btnCount; i ) {
        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:UIControlStateSelected];
        btn.tag = i;
        int row = i / columnCount; // 第幾行
        int column = i % columnCount; //第幾列
        //邊距
        CGFloat margin = (SZSreenWidth – columnCount *btnW)/(columnCount 1);
        //x軸
        CGFloat btnX = margin column *(btnW margin);
        //y軸
        CGFloat btnY =  row *(btnW margin);
        btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
        height = btnH btnY;
        [self addSubview:btn];
    }
    self.frame = CGRectMake(0, viewY, SZSreenWidth, height);
    
}
#pragma mark – 觸控方法
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //拿到觸控的點
    CGPoint point = [self pointWithTouch:touches];
 //根據觸控的點拿到響應的按鈕
    UIButton *btn =[self buttonWithPoint:point];
    if (btn && btn.selected == NO) {
        btn.selected = YES;
         [self.selectedBtns addObject:btn]; //往陣列或者字典新增物件要判斷物件是否存在
    }
    
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //拿到觸控的點
    CGPoint point = [self pointWithTouch:touches];
    //根據觸控的點拿到響應的按鈕
    UIButton *btn =[self buttonWithPoint:point];
    if (btn && btn.selected == NO) {
        btn.selected = YES;
        [self.selectedBtns addObject:btn]; //往陣列或者字典新增物件要判斷物件是否存在
        
    }else{
        self.currentPoint = point;
    }
    [self setNeedsDisplay];
 
   
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if ([self.delegate respondsToSelector:@selector(lockView:didFinishPath:)]) {
        NSMutableString *path =[NSMutableString string];
        for (UIButton *btn in self.selectedBtns) {
            [path appendFormat:@”%ld”,(long)btn.tag];
        }
        [self.delegate lockView:self didFinishPath:path];
    }
    
    //清空按鈕的選中狀態
//    makeObjectsPerformSelector向陣列中的每一個物件傳送方法,setSelected引數為NULL(NO)
    [self.selectedBtns makeObjectsPerformSelector:@selector(setSelected:) withObject:NULL];
    [self.selectedBtns removeAllObjects];
    [self setNeedsDisplay];
}
//觸控被打斷
-(void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self touchesEnded:touches withEvent:event];
}

-(CGPoint)pointWithTouch:(NSSet *)touches
{
    //拿到觸控的點
    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:self];
    return point;
}
-(UIButton *)buttonWithPoint:(CGPoint)point
{
    //根據觸控的點拿到響應的按鈕
    for (UIButton *btn in self.subviews) {
        //第一個引數為矩形框
        //第二個引數為觸控的點
        if (CGRectContainsPoint(btn.frame, point)) {
            return btn;
        }
    }
    return  nil;
    
}

-(void)drawRect:(CGRect)rect
{
    if (self.selectedBtns.count == 0) {
        return;
    }
    UIBezierPath *path = [UIBezierPath bezierPath];
    //線寬
    path.lineWidth = 8;
    //線的樣式
    path.lineJoinStyle = kCGLineCapRound;
    [[UIColor colorWithRed:32/255.0 green:210/255.0 blue:254/255.0 alpha:0.5] set];
    
    for (int i = 0; i < self.selectedBtns.count; i ) {
        UIButton *button = self.selectedBtns[i];
        if (i == 0) {
//            起點
            [path moveToPoint:button.center];
        }else{
            //連線
            [path addLineToPoint:button.center];
        }
    }
    [path addLineToPoint:self.currentPoint];
    [path stroke];
    
}
@end

在ViewController中程式碼

#import “ViewController.h”
#import “SZLockView.h”
@interface ViewController ()<SZLockViewDelegate> 

//這裡提示一下,代理方法在這裡應該有個view.delegate = self;因為這句話在storyboard中實現了所以程式碼中沒有,如果自己 想做,只能自己在這裡新增SZLockView建立一下

@end

@implementation ViewController

– (void)viewDidLoad {
    [super viewDidLoad];
   
}

-(void)lockView:(SZLockView *)lockView didFinishPath:(NSString *)path
{
    NSLog(@”輸出的路徑%@”,path);
    if ([path isEqualToString:@”12345678″]) {
        [self titleString:@”密碼正確”];
    }else {
        [self titleString:@”密碼錯誤”];
    }
}
-(void)titleString:(NSString *)title
{
    UIAlertController *alter =[UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleAlert];
    [alter addAction:[UIAlertAction actionWithTitle:@”確定” style:UIAlertActionStyleDestructive handler:nil]];
    [alter addAction:[UIAlertAction actionWithTitle:@”取消” style:UIAlertActionStyleCancel handler:nil]];
    [self presentViewController:alter animated:YES completion:nil];
}

程式碼在gitHub中,地址:https://github.com/NoPolun/LockView.git