上图是QQ的解锁画面,不知道这样的设计是故意为之还是疏忽,允许隔断连线确实增加了密码复杂性,但是在QQ这里出现了有时候快速划过连不上的问题。。。
所以最好还是采用不允许隔点连线为好。
首先画圆圈
DDYCircleView.h
#import
/** 圆的状态 */
typedef NS_ENUM(NSInteger, DDYCircleViewState) {
DDYCircleViewStateNormal = 1,
DDYCircleViewStateSelected = 2,
DDYCircleViewStateError = 3,
DDYCircleViewStateLastOneSelected = 4,
DDYCircleViewStateLastOneError = 5,
};
/** 圆的用途 */
typedef NS_ENUM(NSInteger, DDYCircleViewType) {
DDYCircleViewTypeInfo = 1,
DDYCircleViewTypeGesture = 2,
};
@interface DDYCircleView : UIView
/** 所处状态 */
@property (nonatomic, assign) DDYCircleViewState state;
/** 类型 */
@property (nonatomic, assign) DDYCircleViewType type;
/** 是否有箭头 默认YES */
@property (nonatomic, assign) BOOL arrow;
/** 角度 */
@property (nonatomic, assign) CGFloat angle;
/** 初始化 */
+ (instancetype)circleView;
@end
DDYCircleView.m
#import "DDYCircleView.h"
@implementation DDYCircleView
+ (instancetype)circleView {
return [[self alloc] init];
}
- (instancetype)init {
if (self = [super init]) {
self.backgroundColor = lockViewBgColor;
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 上下文旋转
[self tansformCtx:ctx rect:rect];
// 画外空心圆
[self drawOutCircleWithCtx:ctx rect:rect];
// 画内实心圆
[self drawInCircleWithCtx:ctx rect:rect];
// 画三角形
[self drawTrangleWithCtx:ctx rect:rect];
}
#pragma mark 上下文旋转
- (void)tansformCtx:(CGContextRef)ctx rect:(CGRect)rect {
CGFloat translateXY = rect.size.width*.5f;
CGContextTranslateCTM(ctx, translateXY, translateXY);
CGContextRotateCTM(ctx, self.angle);
CGContextTranslateCTM(ctx, -translateXY, -translateXY);
}
#pragma mark 画外空心圆
- (void)drawOutCircleWithCtx:(CGContextRef)ctx rect:(CGRect)rect {
CGRect circleRect = DDYRect(outCircleWidth, outCircleWidth, rect.size.width-2*outCircleWidth, rect.size.height-2*outCircleWidth);
CGMutablePathRef circlePath = CGPathCreateMutable();
CGPathAddEllipseInRect(circlePath, NULL, circleRect);
CGContextAddPath(ctx, circlePath);
[[self outCircleColor] set];
CGContextSetLineWidth(ctx, outCircleWidth);
CGContextStrokePath(ctx);
CGPathRelease(circlePath);
}
#pragma mark 画内实心圆
- (void)drawInCircleWithCtx:(CGContextRef)ctx rect:(CGRect)rect {
CGFloat radio = (self.type == DDYCircleViewTypeGesture) ? circleRadio : 1;
CGFloat circleX = rect.size.width/2 * (1-radio) + outCircleWidth;
CGFloat circleY = rect.size.height/2 * (1-radio) + outCircleWidth;
CGFloat circleW = rect.size.width*radio - outCircleWidth*2;
CGFloat circleH = rect.size.height*radio - outCircleWidth*2;
CGMutablePathRef circlePath = CGPathCreateMutable();
CGPathAddEllipseInRect(circlePath, NULL, CGRectMake(circleX, circleY, circleW, circleH));
[[self inCircleColor] set];
CGContextAddPath(ctx, circlePath);
CGContextFillPath(ctx);
CGPathRelease(circlePath);
}
#pragma mark 画三角形
- (void)drawTrangleWithCtx:(CGContextRef)ctx rect:(CGRect)rect {
if (self.arrow) {
CGPoint topPoint = CGPointMake(rect.size.width/2, 10);
CGMutablePathRef trianglePath = CGPathCreateMutable();
CGPathMoveToPoint(trianglePath, NULL, topPoint.x, topPoint.y);
CGPathAddLineToPoint(trianglePath, NULL, topPoint.x - trangleLength/2, topPoint.y + trangleLength/2);
CGPathAddLineToPoint(trianglePath, NULL, topPoint.x + trangleLength/2, topPoint.y + trangleLength/2);
CGContextAddPath(ctx, trianglePath);
[[self trangleColor] set];
CGContextFillPath(ctx);
CGPathRelease(trianglePath);
}
}
#pragma mark 外圆颜色
- (UIColor *)outCircleColor {
UIColor *color;
switch (self.state) {
case DDYCircleViewStateNormal:
color = outCircleNormalColor;
break;
case DDYCircleViewStateSelected:
color = outCircleSelectedColor;
break;
case DDYCircleViewStateError:
color = outCircleErrorColor;
break;
case DDYCircleViewStateLastOneSelected:
color = outCircleSelectedColor;
break;
case DDYCircleViewStateLastOneError:
color = outCircleErrorColor;
break;
default:
color = outCircleNormalColor;
break;
}
return color;
}
#pragma mark 内圆颜色
- (UIColor *)inCircleColor {
UIColor *color;
switch (self.state) {
case DDYCircleViewStateNormal:
color = inCircleNormalColor;
break;
case DDYCircleViewStateSelected:
color = inCircleSelectedColor;
break;
case DDYCircleViewStateError:
color = inCircleErrorColor;
break;
case DDYCircleViewStateLastOneSelected:
color = inCircleSelectedColor;
break;
case DDYCircleViewStateLastOneError:
color = inCircleErrorColor;
break;
default:
color = inCircleNormalColor;
break;
}
return color;
}
#pragma mark 三角颜色
- (UIColor *)trangleColor {
UIColor *color;
switch (self.state) {
case DDYCircleViewStateNormal:
color = trangleNormalColor;
break;
case DDYCircleViewStateSelected:
color = trangleSelectedColor;
break;
case DDYCircleViewStateError:
color = trangleErrorColor;
break;
case DDYCircleViewStateLastOneSelected:
color = trangleSelectedColor;
break;
case DDYCircleViewStateLastOneError:
color = trangleErrorColor;
break;
default:
color = trangleNormalColor;
break;
}
return color;
}
#pragma mark 角度set方法
- (void)setAngle:(CGFloat)angle {
_angle = angle;
[self setNeedsDisplay];
}
#pragma mark 状态set方法
- (void)setState:(DDYCircleViewState)state {
_state = state;
[self setNeedsDisplay];
}
@end
其次将上面的圆圈画成九宫格,形成手势区域
DDYLockView.h
#import
@class DDYLockView;
typedef NS_ENUM(NSInteger, DDYLockViewType) {
DDYLockViewTypeSetting = 1, // 设置手势密码
DDYLockViewTypeLogin = 2, // 登录手势密码
DDYLockViewTypeVerify = 3, // 验证手势密码
};
typedef NS_ENUM(NSInteger, DDYLockViewState) {
DDYLockViewStateLess = 1, // 连线个数少于最小值(设置)
DDYLockViewStateFirstFinish = 2, // 提示再次绘制以确认(设置)
DDYLockViewStateSecondFinish= 3, // 两次绘制一致可保存(设置)
DDYLockViewStateSecondError = 4, // 两次绘制路径不一致(设置)
DDYLockViewStateLoginFinish = 5, // 手势密码登录成功(登录)
DDYLockViewStateLoginError = 6, // 手势密码登录失败(登录)
DDYLockViewStateVerifyFinish= 7, // 修改密码验证成功(验证)
DDYLockViewStateVerifyError = 8, // 修改密码验证失败(验证)
};
//--------------------------- delegate ---------------------------//
@protocol DDYLockViewDelegate
- (void)lockView:(DDYLockView *)lockView state:(DDYLockViewState)state;
@end
//--------------------------- InfoView ---------------------------//
@interface DDYLockInfoView : UIView
+ (instancetype)infoViewWithFrame:(CGRect)frame;
@end
//--------------------------- lockView ---------------------------//
@interface DDYLockView : UIView
/** 是否裁剪 默认YES */
@property (nonatomic, assign) BOOL clip;
/** 是否有箭头 默认YES */
@property (nonatomic, assign) BOOL arrow;
/** 解锁类型 */
@property (nonatomic, assign) DDYLockViewType type;
/** 代理 */
@property (nonatomic, weak) id delegate;
/** 初始化 */
+ (instancetype)lockViewWithType:(DDYLockViewType)type;
+ (instancetype)lockViewWithType:(DDYLockViewType)type clip:(BOOL)clip arrow:(BOOL)arrow;
- (instancetype)initWithType:(DDYLockViewType)type clip:(BOOL)clip arrow:(BOOL)arrow;
@end
DDYLockView.m
#import "DDYLockView.h"
//--------------------------- InfoView ---------------------------//
@implementation DDYLockInfoView
+ (instancetype)infoViewWithFrame:(CGRect)frame {
return [[self alloc] initWithFrame:frame];
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = circleBgColor;
for (int i = 0; i < 9; i++) {
DDYCircleView *circle = [DDYCircleView circleView];
circle.type = DDYCircleViewTypeInfo;
[self addSubview:circle];
}
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat itemViewWH = circleInfoRadius * 2;
CGFloat itemMargin = (self.ddy_w - 3*itemViewWH) / 3.f;
// 九宫格
[self.subviews enumerateObjectsUsingBlock:^(DDYCircleView *circle, NSUInteger idx, BOOL *stop) {
NSUInteger row = idx % 3;
NSUInteger col = idx / 3;
CGFloat x = itemMargin*row + row*itemViewWH + itemMargin/2;
CGFloat y = itemMargin*col + col*itemViewWH + itemMargin/2;
circle.tag = idx + 1;
circle.frame = DDYRect(x, y, itemViewWH, itemViewWH);
}];
}
@end
//--------------------------- lockView ---------------------------//
@interface DDYLockView ()
/** 选中的圆数组 */
@property (nonatomic, strong) NSMutableArray *selectedCircleArray;
/** 当前点位 */
@property (nonatomic, assign) CGPoint currentPoint;
/** 数组清空标识 */
@property (nonatomic, assign) BOOL isCleaned;
@end
@implementation DDYLockView
#pragma mark setter/getter
#pragma mark 设置箭头
- (void)setArrow:(BOOL)arrow {
_arrow = arrow;
// 遍历子控件,改变其是否有箭头
[self.subviews enumerateObjectsUsingBlock:^(DDYCircleView *circle, NSUInteger idx, BOOL *stop) {
[circle setArrow:arrow];
}];
}
- (NSMutableArray *)selectedCircleArray {
if (!_selectedCircleArray) {
_selectedCircleArray = [NSMutableArray array];
}
return _selectedCircleArray;
}
#pragma mark - 初始化
#pragma mark 类方法初始化,默认裁剪有箭头
+ (instancetype)lockViewWithType:(DDYLockViewType)type {
return [[self alloc] initWithType:type clip:YES arrow:YES];
}
+ (instancetype)lockViewWithType:(DDYLockViewType)type clip:(BOOL)clip arrow:(BOOL)arrow {
return [[self alloc] initWithType:type clip:clip arrow:arrow];
}
#pragma mark 初始化方法:初始化type、clip、arrow
- (instancetype)initWithType:(DDYLockViewType)type clip:(BOOL)clip arrow:(BOOL)arrow {
if (self = [super init]) {
[self lockViewPrepare];
self.type = type;
self.clip = clip;
self.arrow = arrow;
}
return self;
}
- (instancetype)init {
if (self = [super init]) {
[self lockViewPrepare];
}
return self;
}
#pragma mark UI
#pragma mark 视图准备
- (void)lockViewPrepare {
self.frame = DDYRect(0, 0, DDYSCREENW-lockViewEdgeMargin*2, DDYSCREENW-lockViewEdgeMargin*2);
self.center = DDYPoint(DDYSCREENW/2, DDYSCREENH*3/5);
self.clip = YES; // 默认裁剪
self.arrow = YES; // 默认有箭头
self.backgroundColor = circleBgColor;
for (int i = 0; i < 9; i++) {
DDYCircleView *circle = [DDYCircleView circleView];
circle.type = DDYCircleViewTypeGesture;
circle.arrow = self.arrow;
[self addSubview:circle];
}
}
#pragma mark 布局子控件
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat itemViewWH = circleRadius * 2;
CGFloat itemMargin = (self.ddy_w - 3*itemViewWH) / 3.f;
// 九宫格
[self.subviews enumerateObjectsUsingBlock:^(DDYCircleView *circle, NSUInteger idx, BOOL *stop) {
NSUInteger row = idx % 3;
NSUInteger col = idx / 3;
CGFloat x = itemMargin*row + row*itemViewWH + itemMargin/2;
CGFloat y = itemMargin*col + col*itemViewWH + itemMargin/2;
circle.tag = idx + 1;
circle.frame = DDYRect(x, y, itemViewWH, itemViewWH);
}];
}
#pragma mark - touch began / touch moved / touch end
#pragma mark touch began
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// 手势重置
[self gestureReset];
self.currentPoint = CGPointZero;
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
[self.subviews enumerateObjectsUsingBlock:^(DDYCircleView *circle, NSUInteger idx, BOOL *stop) {
if (CGRectContainsPoint(circle.frame, point)) {
circle.state = DDYCircleViewStateSelected;
[self.selectedCircleArray addObject:circle];
}
}];
// 数组中最后一个对象的处理
[self.selectedCircleArray lastObject].state = DDYCircleViewStateLastOneSelected;
[self setNeedsDisplay];
}
#pragma mark touch moved
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
self.currentPoint = CGPointZero;
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
[self.subviews enumerateObjectsUsingBlock:^(DDYCircleView *circle, NSUInteger idx, BOOL *stop) {
if (CGRectContainsPoint(circle.frame, point)) {
if (![self.selectedCircleArray containsObject:circle]) {
[self.selectedCircleArray addObject:circle];
// move过程中连线(包含跳跃连线的处理)
[self calculateAngleAndConnectJumpedCircle];
}
} else {
self.currentPoint = point;
}
}];
[self.selectedCircleArray enumerateObjectsUsingBlock:^(DDYCircleView *circle, NSUInteger idx, BOOL *stop) {
circle.state = DDYCircleViewStateSelected;
// 如果是登录或验证密码需要改相应状态
if (self.type == DDYLockViewTypeSetting) {
circle.state = DDYCircleViewStateLastOneSelected;
}
}];
// 数组中最后一个对象的处理
[self.selectedCircleArray lastObject].state = DDYCircleViewStateLastOneSelected;
[self setNeedsDisplay];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
self.isCleaned = NO;
// 拼手势密码字符串
NSMutableString *gesture = [NSMutableString string];
for (DDYCircleView *circle in self.selectedCircleArray) {
[gesture appendFormat:@"%@", @(circle.tag)];
}
CGFloat length = [gesture length];
if (length == 0) return;
if ([self.delegate respondsToSelector:@selector(lockView:state:)]) {
// 手势绘制结果处理
switch (self.type) {
case DDYLockViewTypeSetting:
{
if (length < lockCircleLeast) {
[self.delegate lockView:self state:DDYLockViewStateLess];
[self changeCircleInSelectedCircleArrayWithSate:DDYCircleViewStateError];
} else if ([DDYUserDefaultsGet(lockOneKey) length] < lockCircleLeast) {
DDYUserDefaultsSet(gesture, lockOneKey);
[self.delegate lockView:self state:DDYLockViewStateFirstFinish];
} else if ([gesture isEqual:DDYUserDefaultsGet(lockOneKey)]) {
DDYUserDefaultsSet(gesture, lockEndKey);
[self.delegate lockView:self state:DDYLockViewStateSecondFinish];
} else {
[self.delegate lockView:self state:DDYLockViewStateSecondError];
[self changeCircleInSelectedCircleArrayWithSate:DDYCircleViewStateError];
DDYUserDefaultsSet(nil, lockOneKey);
}
}
break;
case DDYLockViewTypeLogin:
{
if ([gesture isEqual:DDYUserDefaultsGet(lockEndKey)]) {
[self.delegate lockView:self state:DDYLockViewStateLoginFinish];
} else {
[self.delegate lockView:self state:DDYLockViewStateLoginError];
[self changeCircleInSelectedCircleArrayWithSate:DDYCircleViewStateError];
}
}
break;
case DDYLockViewTypeVerify:
{
if ([gesture isEqual:DDYUserDefaultsGet(lockEndKey)]) {
[self.delegate lockView:self state:DDYLockViewStateVerifyFinish];
} else {
[self.delegate lockView:self state:DDYLockViewStateVerifyError];
[self changeCircleInSelectedCircleArrayWithSate:DDYCircleViewStateError];
}
}
break;
}
}
[self errorToDisplay];
}
#pragma mark - 私有操作方法
#pragma mark 手势清空重置操作
- (void)gestureReset {
// 线程安全
@synchronized (self) {
if (!self.isCleaned) {
// 手势完毕,选中的圆回归普通状态
[self changeCircleInSelectedCircleArrayWithSate:DDYCircleViewStateNormal];
// 清空保存选中的数组
[self.selectedCircleArray removeAllObjects];
// 清空方向
[self resetAllCirclesDirection];
// 完成后改变clean状态
self.isCleaned = YES;
}
}
}
#pragma mark 清空所有子控件方向
- (void)resetAllCirclesDirection {
[self.subviews enumerateObjectsUsingBlock:^(DDYCircleView *circle, NSUInteger idx, BOOL *stop) {
circle.angle = 0;
}];
}
#pragma mark 改变选中数组子控件状态
- (void)changeCircleInSelectedCircleArrayWithSate:(DDYCircleViewState)state {
[self.selectedCircleArray enumerateObjectsUsingBlock:^(DDYCircleView *circle, NSUInteger idx, BOOL *stop) {
circle.state = state;
// 如果是错误状态,那就将最后一个按钮特殊处理
if (state == DDYCircleViewStateError && idx == self.selectedCircleArray.count-1) {
circle.state = DDYCircleViewStateLastOneError;
}
}];
[self setNeedsDisplay];
}
#pragma mark 每添加一个圆计算一次方向,同时处理跳跃连线
- (void)calculateAngleAndConnectJumpedCircle {
if (self.selectedCircleArray && self.selectedCircleArray.count>1) {
// 最后一个对象
DDYCircleView *last1 = [self.selectedCircleArray lastObject];
// 倒数第二个对象
DDYCircleView *last2 = self.selectedCircleArray[self.selectedCircleArray.count-2];
// 计算角度(反正切)
last2.angle = atan2(last1.center.y-last2.center.y, last1.center.x-last2.center.x) + M_PI_2;
// 跳跃连线问题
DDYCircleView *jumpedCircle = [self selectedCircleContainPoint:[self centerPointWithPoint1:last1.center point2:last2.center]];
if (jumpedCircle && ![self.selectedCircleArray containsObject:jumpedCircle]) {
// 把跳跃的圆添加到已选择圆的数组(插入到倒数第二个)
[self.selectedCircleArray insertObject:jumpedCircle atIndex:self.selectedCircleArray.count-1];
}
}
}
#pragma mark 提供两个点返回他们中点
- (CGPoint)centerPointWithPoint1:(CGPoint)point1 point2:(CGPoint)point2 {
CGFloat x1 = fmax(point1.x, point2.x);
CGFloat x2 = fmin(point1.x, point2.x);
CGFloat y1 = fmax(point1.y, point2.y);
CGFloat y2 = fmin(point1.y, point2.y);
return CGPointMake((x1+x2)/2, (y1+y2)/2);
}
#pragma mark 判断点是否被圆包含(包含返回圆否则返回nil)
- (DDYCircleView *)selectedCircleContainPoint:(CGPoint)point {
DDYCircleView *centerCircle = nil;
for (DDYCircleView *circle in self.subviews) {
if (CGRectContainsPoint(circle.frame, point)) {
centerCircle = circle;
}
}
if (![self.selectedCircleArray containsObject:centerCircle]) {
// 跳跃的点角度和已选择的倒数第二个角度一致
centerCircle.angle = [self.selectedCircleArray[self.selectedCircleArray.count-2] angle];
}
return centerCircle;
}
#pragma mark 错误回显重绘
- (void)errorToDisplay {
if ([self circleState] == DDYCircleViewStateError || [self circleState] == DDYCircleViewStateLastOneError) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(lockDisplayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self gestureReset];
});
} else {
[self gestureReset];
}
}
#pragma mark 获取当前圆的状态
- (DDYCircleViewState)circleState {
return [self.selectedCircleArray firstObject].state;
}
- (void)drawRect:(CGRect)rect {
// 没有任何选中则return
if (self.selectedCircleArray && self.selectedCircleArray.count) {
UIColor *lineColor = [self circleState]==DDYCircleViewStateError ? lineErrorColor : LineNormalColor;
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextAddRect(ctx, rect);
// 是否裁剪
if (self.clip) {
[self.subviews enumerateObjectsUsingBlock:^(DDYCircleView *circle, NSUInteger idx, BOOL *stop) {
// 确定裁剪的形状
CGContextAddEllipseInRect(ctx, circle.frame);
}];
}
CGContextEOClip(ctx);
for (int i = 0; i
最后利用手势区域生成不同功能(设置手势,验证手势,登录手势)控制器
#import "DDYGestureLockVC.h"
@interface DDYGestureLockVC ()
/** 解锁九宫格 */
@property (nonatomic, strong) DDYLockView *lockView;
/** TypeSetting/TypeLogin 提示文字, TypeVerify清爽无提示 */
@property (nonatomic, strong) UILabel *tipLabel;
/** TypeSetting/TypeLogin 提示视图, TypeVerify清爽无提示 */
@property (nonatomic, strong) DDYLockInfoView *infoView;
@end
@implementation DDYGestureLockVC
- (void)viewDidLoad {
[super viewDidLoad];
[self setupSameUI];
[self setupDifferentUI];
}
#pragma mark UI相同部分
- (void)setupSameUI {
self.view.backgroundColor = lockViewBgColor;
// 解锁九宫格
_lockView = [DDYLockView lockViewWithType:self.lockType];
_lockView.delegate = self;
[self.view addSubview:_lockView];
// 提示文字
_tipLabel = UILabelNew.labFont(DDYFont(14)).labAlignmentCenter();
[self.view addSubview:_tipLabel.viewSetFrame(0,0,DDYSCREENW,16).viewSetCenterY(_lockView.ddy_y-30)];
}
#pragma mark UI不同部分
- (void)setupDifferentUI {
switch (self.lockType) {
case DDYLockViewTypeSetting:
[self setupViewTypeSetting];
break;
case DDYLockViewTypeLogin:
[self setupViewTypeLogin];
break;
case DDYLockViewTypeVerify:
[self setupViewTypeVerify];
break;
}
}
#pragma mark 设置模式界面
- (void)setupViewTypeSetting {
self.navigationItem.title = lockTitleSetting;
self.lockView.type = self.lockType;
[self showNormalMsg:lockTipBeforeSet];
_infoView = [DDYLockInfoView infoViewWithFrame:DDYRect(0, 0, 1.2*circleRadius, 1.2*circleRadius)];
_infoView.center = DDYPoint(DDYSCREENW/2, _tipLabel.ddy_y - _infoView.ddy_h/2-10);
[self.view addSubview:_infoView];
}
#pragma mark 登录模式界面
- (void)setupViewTypeLogin {
self.navigationItem.title = lockTitleLogin;
DDYHeader *header = [DDYHeader headerWithHeaderWH:65];
header.center = DDYPoint(DDYSCREENW/2, DDYSCREENH/5);
header.imgArray = @[[UIImage imageWithColor:DDY_Red size:DDYSize(65, 65)]];
header.urlArray = @[@""];
[self.view addSubview:header];
// 提示请输入手势密码
[self showNormalMsg:lockTipLoginTip];
// 忘记手势密码?
// 指纹解锁
}
#pragma mark 验证模式界面
- (void)setupViewTypeVerify {
self.navigationItem.title = lockTitleSetting;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// 清空第一个密码【登录验证都第二个(不关心第一个),设置从第一个开始(此时第一个为空)】
DDYUserDefaultsSet(nil, lockOneKey);
}
#pragma mark DDYLockViewDelegate and UINavigationControllerDelegate
- (void)lockView:(DDYLockView *)lockView state:(DDYLockViewState)state {
switch (state) {
case DDYLockViewStateLess:
[self showWarningAndShake:lockTipConnectLess];
break;
case DDYLockViewStateFirstFinish:
{
[self showNormalMsg:lockTipDrawAgain];
[self infoViewSelectedSameAsLockView:lockView];
}
break;
case DDYLockViewStateSecondFinish:
{
[self showNormalMsg:lockTipSuccess];
[self.navigationController popToRootViewControllerAnimated:YES];
}
break;
case DDYLockViewStateSecondError:
{
[self showWarningAndShake:lockTipDrawAgainError];
[self infoViewDeselectedAllCircle];
}
break;
case DDYLockViewStateLoginFinish:
[self dismissViewControllerAnimated:YES completion:^{ }];
break;
case DDYLockViewStateLoginError:
[self showWarningAndShake:lockTipVerifyError];
break;
case DDYLockViewStateVerifyFinish:
[self dismissViewControllerAnimated:YES completion:^{ }];
break;
case DDYLockViewStateVerifyError:
[self showWarningAndShake:lockTipVerifyError];
break;
}
}
#pragma mark - tipLabel不同提示
#pragma mark 普通提示
- (void)showNormalMsg:(NSString *)msg {
[_tipLabel setText:msg];
[_tipLabel setTextColor:lockTipNormalColor];
}
#pragma mark 摇动警示
- (void)showWarningAndShake:(NSString *)msg {
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.x"];
animation.values = @[@(-5),@(0),@(5),@(0),@(-5),@(0),@(5),@(0)];
animation.duration = 0.3f;
animation.repeatCount = 2;
animation.removedOnCompletion = YES;
[_tipLabel setText:msg];
[_tipLabel setTextColor:lockTipWarningColor];
[_tipLabel.layer addAnimation:animation forKey:@"shake"];
}
#pragma mark - infoView操作
#pragma mark 设置状态第一次设置后infoView展示相应选中
- (void)infoViewSelectedSameAsLockView:(DDYLockView *)lockView {
for (DDYCircleView *circle in lockView.subviews) {
if (circle.state==DDYCircleViewStateSelected || circle.state==DDYCircleViewStateLastOneSelected) {
for (DDYCircleView *infoCircle in _infoView.subviews) {
if (infoCircle.tag == circle.tag) {
infoCircle.state = DDYCircleViewStateSelected;
}
}
}
}
}
#pragma mark 让infoView按钮全部取消选中
- (void)infoViewDeselectedAllCircle {
[_infoView.subviews enumerateObjectsUsingBlock:^(DDYCircleView *circle, NSUInteger idx, BOOL *stop) {
circle.state = DDYCircleViewStateNormal;
}];
}
@end