首页 » 技术分享 » [汇文教育]手势密码SDK

[汇文教育]手势密码SDK

 

目前手机上的开机进入页面和支付页面都会有手势密码,设置该密码主要是为了增加安全性和便捷度。那么下面就详细介绍下手势密码是如何实现的。

首先要导入的是:

这几个文件就是需要的框架。

第一步:设置密码,首先要有设置密码的九宫格。代码如下

该方法就是密码的设置以及保存到本地,以便下次验证密码使用

第二步:密码的验证:代码如下

第三步:以上两步是密码的设置与验证,但是如何讲手势密码保存还有密码九宫格的ui设计呢?代码如下:以下代码是九宫格中单个uiview的布局

#import "YLSwipeLockNodeView.h"

#import "YLSwipeLockView.h"

@interface YLSwipeLockNodeView()

@property (nonatomic, strong)CAShapeLayer *outlineLayer;

@property (nonatomic, strong)CAShapeLayer *innerCircleLayer;

@end

@implementation YLSwipeLockNodeView

-(id)initWithFrame:(CGRect)frame

{

    self = [super initWithFrame:frame];

    if (self) {

        [self.layer addSublayer:self.outlineLayer];

        [self.layer addSublayer:self.innerCircleLayer];

        self.nodeViewStatus = YLSwipeLockNodeViewStatusNormal;

    }

    return self;

}

-(void)pan:(UIPanGestureRecognizer *)rec

{

    NSLog(@"what the fuck");

    CGPoint point = [rec locationInView:self];

    NSLog(@"location in view:%f, %f", point.x, point.y);

    self.nodeViewStatus = YLSwipeLockNodeViewStatusSelected;

}

-(void)setNodeViewStatus:(YLSwipeLockNodeViewStatus)nodeViewStatus

{

    _nodeViewStatus = nodeViewStatus;

    switch (_nodeViewStatus) {

        case YLSwipeLockNodeViewStatusNormal:

            [self setStatusToNormal];

            break;

        case YLSwipeLockNodeViewStatusSelected:

            [self setStatusToSelected];

            break;

        case YLSwipeLockNodeViewStatusWarning:

            [self setStatusToWarning];

            break;

        default:

            break;

    }

}

-(void)setStatusToNormal

{

    self.outlineLayer.strokeColor = [UIColor whiteColor].CGColor;

    self.innerCircleLayer.fillColor = [UIColor clearColor].CGColor;

}

-(void)setStatusToSelected

{

    self.outlineLayer.strokeColor = LIGHTBLUE.CGColor;

    self.innerCircleLayer.fillColor = LIGHTBLUE.CGColor;

}

-(void)setStatusToWarning

{

    self.outlineLayer.strokeColor = [UIColor redColor].CGColor;

    self.innerCircleLayer.fillColor = [UIColor redColor].CGColor;

    

}

-(void)layoutSubviews

{

    self.outlineLayer.frame = self.bounds;

    UIBezierPath *outlinePath = [UIBezierPath bezierPathWithOvalInRect:self.bounds];

    self.outlineLayer.path = outlinePath.CGPath;

    

    CGRect frame = self.bounds;

    CGFloat width = frame.size.width / 3;

    self.innerCircleLayer.frame = CGRectMake(width, width, width, width);

    UIBezierPath *innerPath = [UIBezierPath bezierPathWithOvalInRect:self.innerCircleLayer.bounds];

    self.innerCircleLayer.path = innerPath.CGPath;

}

-(CAShapeLayer *)outlineLayer

{

    if (_outlineLayer == nil) {

        _outlineLayer = [[CAShapeLayer alloc] init];

        _outlineLayer.strokeColor = LIGHTBLUE.CGColor;

        _outlineLayer.lineWidth = 1.0f;

        _outlineLayer.fillColor  = [UIColor clearColor].CGColor;

    }

    return _outlineLayer;

}

-(CAShapeLayer *)innerCircleLayer

{

    if (_innerCircleLayer == nil) {

        _innerCircleLayer = [[CAShapeLayer alloc] init];

        _innerCircleLayer.strokeColor = [UIColor clearColor].CGColor;

        _innerCircleLayer.lineWidth = 1.0f;

        _innerCircleLayer.fillColor  = LIGHTBLUE.CGColor;

    }

    return _innerCircleLayer;

}

第四步:九宫格的布局以及将手势保存

#import "YLSwipeLockView.h"

#import "YLSwipeLockNodeView.h"

@interface YLSwipeLockView()

@property (nonatomic, strong) NSMutableArray *nodeArray;

@property (nonatomic, strong) NSMutableArray *selectedNodeArray;

@property (nonatomic, strong) CAShapeLayer *polygonalLineLayer;

@property (nonatomic, strong) UIBezierPath *polygonalLinePath;

@property (nonatomic, strong) NSMutableArray *pointArray;

@property (nonatomic) YLSwipeLockViewState viewState;

@end

@implementation YLSwipeLockView

-(id)initWithFrame:(CGRect)frame{

    self = [super initWithFrame:frame];

    if (self) {

        

        [self.layer addSublayer:self.polygonalLineLayer];

        

        _nodeArray = [NSMutableArray arrayWithCapacity:9];

        for (int i = 0; i < 9; ++i) {

            YLSwipeLockNodeView *nodeView = [YLSwipeLockNodeView new];

            [_nodeArray addObject:nodeView];

            nodeView.tag = i;

            [self addSubview:nodeView];

        }

        _selectedNodeArray = [NSMutableArray arrayWithCapacity:9];

        _pointArray = [NSMutableArray array];

        

        UIPanGestureRecognizer *panRec = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];

        [self addGestureRecognizer:panRec];

        self.viewState = YLSwipeLockNodeViewStatusNormal;

        [self cleanNodes];

        

    }

    return self;

}

-(void)pan:(UIPanGestureRecognizer *)rec

{

    if  (rec.state == UIGestureRecognizerStateBegan){

        self.viewState = YLSwipeLockNodeViewStatusNormal;

    }

    

    CGPoint touchPoint = [rec locationInView:self];

    NSInteger index = [self indexForNodeAtPoint:touchPoint];

    if (index >= 0) {

        YLSwipeLockNodeView *node = self.nodeArray[index];

        

        if (![self addSelectedNode:node]) {

            [self moveLineWithFingerPosition:touchPoint];

        }

    }else{

        [self moveLineWithFingerPosition:touchPoint];

        

    }

    

    if (rec.state == UIGestureRecognizerStateEnded) {

        

        [self removeLastFingerPosition];

        if([self.delegate respondsToSelector:@selector(swipeView:didEndSwipeWithPassword:)]){

            NSMutableString *password = [NSMutableString new];

            for(YLSwipeLockNodeView *nodeView in self.selectedNodeArray){

                NSString *index = [@(nodeView.tag) stringValue];

                [password appendString:index];

            }

            self.viewState = [self.delegate swipeView:self didEndSwipeWithPassword:password];

            

        }

        else{

            self.viewState = YLSwipeLockViewStateSelected;

        }

    }

    

}

-(BOOL)addSelectedNode:(YLSwipeLockNodeView *)nodeView

{

    if (![self.selectedNodeArray containsObject:nodeView]) {

        nodeView.nodeViewStatus = YLSwipeLockNodeViewStatusSelected;

        [self.selectedNodeArray addObject:nodeView];

        

        [self addLineToNode:nodeView];

        

        return YES;

    }else{

        return NO;

    }

    

}

-(void)addLineToNode:(YLSwipeLockNodeView *)nodeView

{

    if(self.selectedNodeArray.count == 1){

        

        //path move to start point

        CGPoint startPoint = nodeView.center;

        [self.polygonalLinePath moveToPoint:startPoint];

        [self.pointArray addObject:[NSValue valueWithCGPoint:startPoint]];

        self.polygonalLineLayer.path = self.polygonalLinePath.CGPath;

        

    }else{

        

        //path add line to point

        [self.pointArray removeLastObject];

        CGPoint middlePoint = nodeView.center;

        [self.pointArray addObject:[NSValue valueWithCGPoint:middlePoint]];

        

        [self.polygonalLinePath removeAllPoints];

        CGPoint startPoint = [self.pointArray[0] CGPointValue];

        [self.polygonalLinePath moveToPoint:startPoint];

        

        for (int i = 1; i < self.pointArray.count; ++i) {

            CGPoint middlePoint = [self.pointArray[i] CGPointValue];

            [self.polygonalLinePath addLineToPoint:middlePoint];

        }

        self.polygonalLineLayer.path = self.polygonalLinePath.CGPath;

        

    }

}

-(void)moveLineWithFingerPosition:(CGPoint)touchPoint

{

    if (self.pointArray.count > 0) {

        if (self.pointArray.count > self.selectedNodeArray.count) {

            [self.pointArray removeLastObject];

        }

        [self.pointArray addObject:[NSValue valueWithCGPoint:touchPoint]];

        [self.polygonalLinePath removeAllPoints];

        CGPoint startPoint = [self.pointArray[0] CGPointValue];

        [self.polygonalLinePath moveToPoint:startPoint];

        

        for (int i = 1; i < self.pointArray.count; ++i) {

            CGPoint middlePoint = [self.pointArray[i] CGPointValue];

            [self.polygonalLinePath addLineToPoint:middlePoint];

        }

        self.polygonalLineLayer.path = self.polygonalLinePath.CGPath;

        

    }

}

-(void)removeLastFingerPosition

{

    if (self.pointArray.count > 0) {

        if (self.pointArray.count > self.selectedNodeArray.count) {

            [self.pointArray removeLastObject];

        }

        [self.polygonalLinePath removeAllPoints];

        CGPoint startPoint = [self.pointArray[0] CGPointValue];

        [self.polygonalLinePath moveToPoint:startPoint];

        

        for (int i = 1; i < self.pointArray.count; ++i) {

            CGPoint middlePoint = [self.pointArray[i] CGPointValue];

            [self.polygonalLinePath addLineToPoint:middlePoint];

        }

        self.polygonalLineLayer.path = self.polygonalLinePath.CGPath;

        

    }

}

-(void)layoutSubviews{

    

    self.polygonalLineLayer.frame = self.bounds;

    CAShapeLayer *maskLayer = [CAShapeLayer new];

    maskLayer.frame = self.bounds;

    

    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRect:self.bounds];

    maskLayer.fillRule = kCAFillRuleEvenOdd;

    maskLayer.lineWidth = 1.0f;

    maskLayer.strokeColor = [UIColor blackColor].CGColor;

    maskLayer.fillColor = [UIColor blackColor].CGColor;

    //TODO: here should be more decent

    for (int i = 0; i < self.nodeArray.count; ++i) {

        YLSwipeLockNodeView *nodeView = _nodeArray[i];

        // TODO: change to use MIN marco in the future

        CGFloat min = self.bounds.size.width < self.bounds.size.height ? self.bounds.size.width : self.bounds.size.height;

        CGFloat width = min / 5;

        CGFloat height = min / 5;

        int row = i % 3;

        int column = i / 3;

        CGRect frame = CGRectMake(row *(width * 2), column * (width *2), width, height);

        nodeView.frame = frame;

        [maskPath appendPath:[UIBezierPath bezierPathWithOvalInRect:frame]];

    }

    

    maskLayer.path = maskPath.CGPath;

    self.polygonalLineLayer.mask = maskLayer;

}

-(NSInteger)indexForNodeAtPoint:(CGPoint)point

{

    for (int i = 0; i < self.nodeArray.count; ++i) {

        YLSwipeLockNodeView *node = self.nodeArray[i];

        CGPoint pointInNode = [node convertPoint:point fromView:self];

        if ([node pointInside:pointInNode withEvent:nil]) {

            NSLog(@"点中了第%d~~", i);

            return i;

        }

    }

    return -1;

}

-(void)cleanNodes

{

    for (int i = 0; i < self.nodeArray.count; ++i) {

        YLSwipeLockNodeView *node = self.nodeArray[i];

        node.nodeViewStatus = YLSwipeLockNodeViewStatusNormal;

    }

    

    [self.selectedNodeArray removeAllObjects];

    [self.pointArray removeAllObjects];

    self.polygonalLinePath = [UIBezierPath new];

    self.polygonalLineLayer.strokeColor = LIGHTBLUE.CGColor;

    self.polygonalLineLayer.path = self.polygonalLinePath.CGPath;

}

-(void)cleanNodesIfNeeded{

    if(self.viewState != YLSwipeLockNodeViewStatusNormal){

        [self cleanNodes];

    }

}

-(void)makeNodesToWarning

{

    for (int i = 0; i < self.selectedNodeArray.count; ++i) {

        YLSwipeLockNodeView *node = self.selectedNodeArray[i];

        node.nodeViewStatus = YLSwipeLockNodeViewStatusWarning;

    }

    self.polygonalLineLayer.strokeColor = [UIColor redColor].CGColor;

}

-(CAShapeLayer *)polygonalLineLayer

{

    if (_polygonalLineLayer == nil) {

        _polygonalLineLayer = [[CAShapeLayer alloc] init];

        _polygonalLineLayer.lineWidth = 1.0f;

        _polygonalLineLayer.strokeColor = LIGHTBLUE.CGColor;

        _polygonalLineLayer.fillColor = [UIColor clearColor].CGColor;

    }

    return _polygonalLineLayer;

}

-(void)setViewState:(YLSwipeLockViewState)viewState

{

//    if(_viewState != viewState){

        _viewState = viewState;

        switch (_viewState){

            case YLSwipeLockViewStateNormal:

                [self cleanNodes];

                break;

            case YLSwipeLockViewStateWarning:

                [self makeNodesToWarning];

                [self performSelector:@selector(cleanNodesIfNeeded) withObject:nil afterDelay:1];

                break;

            case YLSwipeLockViewStateSelected:

            default:

                break;

        }

//    }

}

以上就是手势密码的完整代码。

转载自原文链接, 如需删除请联系管理员。

原文链接:[汇文教育]手势密码SDK,转载请注明来源!

0