目前手机上的开机进入页面和支付页面都会有手势密码,设置该密码主要是为了增加安全性和便捷度。那么下面就详细介绍下手势密码是如何实现的。
首先要导入的是:
这几个文件就是需要的框架。
第一步:设置密码,首先要有设置密码的九宫格。代码如下
该方法就是密码的设置以及保存到本地,以便下次验证密码使用
第二步:密码的验证:代码如下
第三步:以上两步是密码的设置与验证,但是如何讲手势密码保存还有密码九宫格的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;
}
// }
}
以上就是手势密码的完整代码。