十三 iOS之 手势解锁

现在好多app都有手势解锁的功能,这个功能要连线,所以和绘制是脱不开关系的,来看看怎么做

示例图一
这里写图片描述

示例图二
这里写图片描述

创建一个UIView–BackView,用来绘制深黑色背景图
  • BackView.m
#import "BackView.h"

@implementation BackView

- (void)drawRect:(CGRect)rect {
    //绘制一个背景图
    UIImage * image = [UIImage imageNamed:@"Home_refresh_bg"];

    [image drawInRect:rect];



}
再创建一个UIView –LockView,用来添加按钮、绘制曲线, 我都是在storyBoard中拖入的
  • LockView.m
#import "LockView.h"

@interface LockView()

@property(nonatomic,assign)CGPoint curP;

/**选中的按钮的数组*/
@property(nonatomic,strong)NSMutableArray * selectedBtnArr;

@end

@implementation LockView

-(NSMutableArray *)selectedBtnArr
{
    if (_selectedBtnArr == nil) {
        _selectedBtnArr = [NSMutableArray array];
    }
    return _selectedBtnArr;
}



//storyBoard拖过来的pan手势
-(IBAction)pan:(UIPanGestureRecognizer*)pan
{
    //当前触摸点
    _curP = [pan locationInView:self];

    //判断触摸点在不在按钮上
    for (UIButton * btn in self.subviews) {
        if (CGRectContainsPoint(btn.frame, self.curP) && btn.selected == NO) {

            btn.selected = YES;

            //保存到数组中
            [self.selectedBtnArr addObject:btn];
        }


    }

    //重绘
    [self setNeedsDisplay];

    if (pan.state == UIGestureRecognizerStateEnded) {
        //创建可变字符串
        NSMutableString * strM = [NSMutableString string];
        //保存输入密码
        for (UIButton * btn in self.selectedBtnArr) {

            //取消所有按钮的选中
            btn.selected = NO;

            //拼接密码
            [strM appendFormat:@"%ld",btn.tag];

        }
        //打印密码
        NSLog(@"密码: %@",strM);

        //清除划线,把选中按钮清空
        [self.selectedBtnArr removeAllObjects];

    }
}


-(void)awakeFromNib
{
    [super awakeFromNib];

    //创建9个按钮
    for (int i = 0; i < 9; i++) {
        UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom];
        //关闭交互,防止高亮
        btn.userInteractionEnabled = NO;
        //设置图片
        [btn setImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];
        [btn setImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected];
        //设置tag值
        btn.tag = i;

        [self addSubview:btn];
    }
}

//布局9个按钮
-(void)layoutSubviews

{
    [super layoutSubviews];

    NSUInteger count = self.subviews.count;
    //总列数
    int cols = 3;

    CGFloat x = 0;
    CGFloat y = 0;
    CGFloat w = 74;
    CGFloat h = 74;
    CGFloat margin = (self.bounds.size.width - cols * w) / (cols + 1);

    //第几列
    CGFloat col = 0;
    //第几行
    CGFloat row = 0;


    for (NSUInteger i = 0; i< count; i++) {
        UIButton * btn = self.subviews[i];

        //当前按钮在第几列
        col = i % cols;
        //当前按钮在第几行
        row = i / cols;

        x = margin + col * (margin + w);
        y = row * (margin + w);



        btn.frame = CGRectMake(x, y, w, h);


    }


}




//只要调用这个方法,就会把之前绘制的东西全部清掉,重新绘制
-(void)drawRect:(CGRect)rect
{
    //    NSLog(@"%s",__func__);
    //没有选中按钮就不需要连线
    if (self.selectedBtnArr.count == 0) return;


    //把所有选中按钮中心连线
    UIBezierPath * path = [UIBezierPath bezierPath];

    NSUInteger count = self.selectedBtnArr.count;

    //所有选中选中按钮之间都连好线
    for (int i = 0; i < count; i++) {
        UIButton * btn = self.selectedBtnArr[i];
        if (i == 0) {
            //设置起点
            [path moveToPoint:btn.center];

        }else
        {
            [path addLineToPoint:btn.center];
        }
    }

    //所有触摸点间连线
    [path addLineToPoint:_curP];

    [[UIColor greenColor]set];
    path.lineWidth = 10;
    //线的转折点设置为圆状
    path.lineJoinStyle = kCGLineJoinRound;

    [path stroke];
}






@end

GitHub demo: GestureUnlock

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是手势解锁的Demo实现过程: 1. 首先创建一个UIView的子类,作为手势解锁的主体视图,我们称之为`GestureLockView`。 2. 在`GestureLockView`中创建一个数组`circleArray`,用于存储手势解锁的圆点。 ``` @property (nonatomic, strong) NSMutableArray *circleArray; ``` 3. 在`GestureLockView`的`layoutSubviews`方法中,创建9个圆点,并加入到`circleArray`中。 ``` - (void)layoutSubviews { [super layoutSubviews]; CGFloat margin = (self.frame.size.width - 3 * kCircleSize) / 4.0; for (int i = 0; i < 9; i++) { CGFloat x = margin + (i % 3) * (margin + kCircleSize); CGFloat y = margin + (i / 3) * (margin + kCircleSize); CGRect frame = CGRectMake(x, y, kCircleSize, kCircleSize); GestureLockCircle *circle = [[GestureLockCircle alloc] initWithFrame:frame]; circle.tag = i + 1; [self addSubview:circle]; [self.circleArray addObject:circle]; } } ``` 4. 在`GestureLockView`中创建一个数组`selectedArray`,用于存储用户选择的圆点。 ``` @property (nonatomic, strong) NSMutableArray *selectedArray; ``` 5. 在`GestureLockView`中实现手势识别的方法`touchesMoved:withEvent:`,通过判断触摸点是否在圆点内来确定用户选择的圆点,并绘制用户选择的线条。 ``` - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint point = [touch locationInView:self]; for (GestureLockCircle *circle in self.circleArray) { if (CGRectContainsPoint(circle.frame, point) && !circle.selected) { circle.selected = YES; [self.selectedArray addObject:circle]; break; } } self.currentPoint = point; [self setNeedsDisplay]; } ``` 6. 在`GestureLockView`中实现绘制方法`drawRect:`,根据用户选择的圆点绘制线条。 ``` - (void)drawRect:(CGRect)rect { if (self.selectedArray.count == 0) { return; } UIBezierPath *path = [UIBezierPath bezierPath]; path.lineWidth = kLineWidth; path.lineJoinStyle = kCGLineJoinRound; path.lineCapStyle = kCGLineCapRound; [[UIColor whiteColor] set]; for (int i = 0; i < self.selectedArray.count; i++) { GestureLockCircle *circle = self.selectedArray[i]; if (i == 0) { [path moveToPoint:circle.center]; } else { [path addLineToPoint:circle.center]; } } [path addLineToPoint:self.currentPoint]; [path stroke]; } ``` 7. 在`GestureLockView`中实现手势结束的方法`touchesEnded:withEvent:`,判断用户手势是否正确,并通过代理方法通知外部。 ``` - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { NSMutableString *password = [NSMutableString string]; for (GestureLockCircle *circle in self.selectedArray) { [password appendFormat:@"%ld", circle.tag]; } BOOL success = [password isEqualToString:self.password]; if (success) { for (GestureLockCircle *circle in self.selectedArray) { circle.selected = NO; } [self.selectedArray removeAllObjects]; [self setNeedsDisplay]; if (self.delegate && [self.delegate respondsToSelector:@selector(gestureLockView:didCompleteWithPassword:)]) { [self.delegate gestureLockView:self didCompleteWithPassword:password]; } } else { for (GestureLockCircle *circle in self.selectedArray) { circle.selected = NO; circle.error = YES; } [self.selectedArray removeAllObjects]; [self setNeedsDisplay]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kErrorDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ for (GestureLockCircle *circle in self.circleArray) { circle.error = NO; } [self setNeedsDisplay]; }); } } ``` 8. 在外部创建`GestureLockView`实例,并设置代理方法,实现手势解锁的逻辑。 ``` - (void)viewDidLoad { [super viewDidLoad]; GestureLockView *lockView = [[GestureLockView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenWidth)]; lockView.center = self.view.center; lockView.delegate = self; lockView.password = @"123456789"; [self.view addSubview:lockView]; } #pragma mark - GestureLockViewDelegate - (void)gestureLockView:(GestureLockView *)lockView didCompleteWithPassword:(NSString *)password { NSLog(@"password: %@", password); } ``` 至此,手势解锁的Demo已经完成了,你可以尝试在模拟器或真机上运行它。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值