iOS 开发实战-锁屏界面(手势解锁)

来源:互联网 发布:人工智能会计师 编辑:程序博客网 时间:2024/04/30 17:02

之前写了一篇关于锁屏的文章,是密码锁屏,可以参照:

该篇是要讲解如何开发手势解锁,完整代码在github上。

关于如何在App后台启动等问题,该篇就不再赘述,之专注于介绍核心的实现部分。源代码在Github上可以获取。

实现思路

手势锁屏是一个3*3的9宫格界面,将每一个宫格用一个Button表示,然后给每一个button附上一个tag,捕捉touch事件,通过判断手势划过哪些button,纪录下tag数值,作为密码。

变量定义

手势锁屏是定义在GuestureView的UIView类中。主要的UI和事件响应都在这个类中完成。

[code]

@interface GuestureView()@property (nonatomic,strong) NSMutableArray * buttonsArray;@property (nonatomic,assign) CGPoint currentPoi;


定义两个变量:

buttonsArray:用来记录划过哪些Button

currentPoi用:来记录当前手指所在的point

UI布局

定义9个UIButton控件

[code]

-(id)initWithFrame:(CGRect)frame{    self = [super initWithFrame:frame];    if (self) {        [self configButtons];    }    return self;}-(void)configButtons{        self.buttonsArray = [NSMutableArray array];    for (int i = 0 ; i < 9 ; ++i) {        UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom];        btn.tag = i;        btn.userInteractionEnabled = NO;        [self addSubview:btn];        [btn setBackgroundImage:[UIImage imageNamed:@"lock"] forState:UIControlStateNormal];        [btn setBackgroundImage:[UIImage imageNamed:@"unlock"] forState:UIControlStateSelected];    }}-(void)layoutSubviews{    [super layoutSubviews];    for(int i = 0 ; i < [self.subviews count] ; ++i) {        UIButton *btn=self.subviews[i];        CGFloat row = i/3;        CGFloat loc   = i%3;        CGFloat btnW=74;        CGFloat btnH=74;        CGFloat padding=(self.frame.size.width-3*btnW)/4;        CGFloat btnX=padding+(btnW+padding)*loc;        CGFloat btnY=padding+(btnW+padding)*row;        btn.frame=CGRectMake(btnX, btnY, btnW, btnH);    }        //密码提示Label    UILabel * passwordLabel = [[UILabel alloc] init];    passwordLabel.text = @"密码是:L";    passwordLabel.textColor = [UIColor grayColor];    [passwordLabel sizeToFit];    [self addSubview:passwordLabel];    passwordLabel.translatesAutoresizingMaskIntoConstraints = NO;    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-400-[passwordLabel]"                                                                 options:0                                                                 metrics:nil                                                                   views:NSDictionaryOfVariableBindings(passwordLabel)]];}

每个Button都赋给一个tag,且userInteractionEnabled为NO。

Button的frame在layoutSubviews里设置。

手势响应

主要实现三个touch事件:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

这三个事件是手势解锁的核心代码。

[code]

#pragma mark - touch event-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{    CGPoint startPoint = [self getCurrentPoint:touches];    UIButton * btn = [self getButtonWithCurrentPoint:startPoint];    if (btn && btn.selected != YES) {        btn.selected = YES;        [self.buttonsArray addObject:btn];    }    self.currentPoi = startPoint;    [self setNeedsDisplay];    }-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{    CGPoint point = [self getCurrentPoint:touches];    UIButton * btn = [self getButtonWithCurrentPoint:point];    if (btn && btn.selected != YES) {        btn.selected = YES;        [self.buttonsArray addObject:btn];    }    [self setNeedsDisplay];    self.currentPoi = point;}-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{    NSMutableString * passWordString = [[NSMutableString alloc] init];    for (UIButton * btn in self.buttonsArray) {        [passWordString appendFormat:@"%ld", (long)btn.tag];    }    NSLog(@"password is %@",passWordString);        [self.buttonsArray makeObjectsPerformSelector:@selector(setSelected:) withObject:@NO];    [self.buttonsArray removeAllObjects];    [self setNeedsDisplay];    self.currentPoi = CGPointZero;        if ([self.delegate respondsToSelector:@selector(unlockFromGuesture:)]) {        if ([passWordString isEqualToString:@"03678"])        {            [self.delegate unlockFromGuesture:YES];        }        else        {            [self.delegate unlockFromGuesture:NO];        }    }}


其中touchedEnded中调用了一个delegate方法,这个方法是为通知superView密码是否正确,然后交给superview来处理。

代码中涉及到两个方法:

//获得当前手指所在point-(CGPoint)getCurrentPoint:(NSSet *)touches//获得该点所在的Button。-(UIButton *)getButtonWithCurrentPoint:(CGPoint)point

[code]

#pragma mark - point event-(CGPoint)getCurrentPoint:(NSSet *)touches{    UITouch * touch = [touches anyObject];    CGPoint point = [touch locationInView:touch.view];    return point;}-(UIButton *)getButtonWithCurrentPoint:(CGPoint)point{    for (UIButton * btn in self.subviews) {        if (CGRectContainsPoint(btn.frame, point)) {            return btn;        }    }    return nil;}

绘图

用Core Graphic实现划线效果。

[code]

- (void)drawRect:(CGRect)rect {    CGContextRef context = UIGraphicsGetCurrentContext();    CGContextClearRect(context, rect);        for (int i = 0; i < self.buttonsArray.count; ++i) {        UIButton * btn = self.buttonsArray[i];        if (0 == i)        {            CGContextMoveToPoint(context, btn.center.x, btn.center.y);        }        else        {            CGContextAddLineToPoint(context, btn.center.x,btn.center.y);        }    }        if (self.buttonsArray.count > 0) {        CGContextAddLineToPoint(context, self.currentPoi.x, self.currentPoi.y);    }        CGContextSetLineWidth(context, 10);    CGContextSetLineJoin(context, kCGLineJoinRound);    CGContextSetLineCap(context, kCGLineCapRound);    CGContextSetRGBStrokeColor(context, 20/255.0, 107/255.0, 153/255.0, 1);    CGContextStrokePath(context);    CGContextSaveGState(context);    CGContextRestoreGState(context);}
该实现放在drawRect方法中,每当调用setNeedsDisplay方法是都会执行drawRect。


如果有任何问题欢迎再下面留言,或者扫描二维码

0 0
原创粉丝点击