手势滑动解锁

思路

  • 遍历生成且设置按钮
  • 当手指点击或者滑动的时候拿到当前触摸点,遍历每一个按钮,将当前触摸点转换为按钮上点,判断时候在按钮上
  • 如果在按钮上,设置当前按钮为选中状态,添加到选中按钮数组中
  • 在drawInRect:中画线,遍历每一个按钮,让第一个按钮的中心点为线段的起点
  • 松开手指时,清空选中按钮数组中的值,重绘
    这里写图片描述
@interface LockView ()

@property (nonatomic, assign) CGPoint curP;
@property (nonatomic, strong) NSMutableArray *selectedBtns;

@end

@implementation LockView

- (NSMutableArray *)selectedBtns
{
    if (_selectedBtns == nil) {
        _selectedBtns = [NSMutableArray array];
    }
    return _selectedBtns;
}

// 画线
// drawRect每次调用,都会把之前的内容全部清空
- (void)drawRect:(CGRect)rect
{

    // 没有选中按钮就不画线
    if (self.selectedBtns.count == 0) return;

    // 拼接路径
    UIBezierPath *path = [UIBezierPath bezierPath];

    int i = 0;
    // 连接所有的选中按钮
    for (UIButton *selBtn in self.selectedBtns) {
        if (i == 0) {
            // 设置起点,起点是第一个选中按钮的中心点
            [path moveToPoint:selBtn.center];
        }else{
            [path addLineToPoint:selBtn.center];
        }

        i++;
    }

    // 添加一根线到手势的触摸点
    [path addLineToPoint:_curP];

    // 颜色
    [[UIColor greenColor] set];

    // 设置路径的线宽
    path.lineWidth = 10;

    path.lineJoinStyle = kCGLineJoinRound;


    // 画线
    [path stroke];

}

// 手指在手势解锁view点击的时候调用
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 选中按钮
    [self selectBtnWithTouches:touches withEvent:event];

}

// 手指在手势解锁view移动的时候调用
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 选中按钮
    [self selectBtnWithTouches:touches withEvent:event];

    // 重绘
    [self setNeedsDisplay];
}

// 手指在手势解锁view抬起的时候调用
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSMutableString *strM = [NSMutableString string];

    // 让所有选中按钮恢复成正常状态
    for (UIButton *selBtn in self.selectedBtns) {
        selBtn.selected = NO;

        // 拼接密码字符串
        [strM appendFormat:@"%ld",selBtn.tag];


    }

    NSLog(@"%@",strM);

    // 清空选中按钮数组
    [self.selectedBtns removeAllObjects];

    // 把之前绘制线清空
    [self setNeedsDisplay];
}

// 选中按钮
- (void)selectBtnWithTouches:(NSSet *)touches withEvent:(UIEvent *)event
{
    // UITouch
    UITouch *touch = [touches anyObject];

    // 获取当前触摸点
    CGPoint curP = [touch locationInView:self];

    // 记录下当前移动触摸点
    _curP = curP;

    // 判断下在不在按钮上
    for (UIButton *btn in self.subviews) {

        // 转换成按钮坐标系上的点
        CGPoint btnP =  [self convertPoint:curP toView:btn];

        // 判断当前点在按钮上并且按钮没有选中
        if ([btn pointInside:btnP withEvent:event] && btn.selected == NO) {
            // 点在按钮上,把按钮选中
            btn.selected = YES;

            // 记录选中的按钮
            [self.selectedBtns addObject:btn];
        }
    }
}

// 当从xib加载完成的时候调用
- (void)awakeFromNib
{
    // 添加9个按钮
    for (int i = 0; i < 9; i++) {

        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];

        btn.tag = i;

        // 正常
        [btn setImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];

        // 选中:选中状态下的图片可以一直保持
        [btn setImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected];
        // 如何判断按钮的图片是高亮还是选中,选中状态的图片可以一直保持
        // 按钮的选中状态只能通过代码实现
        // 按钮的高亮状态是系统默认达到,只要当用户一点击按钮,系统就会自动让达到高亮状态

        btn.userInteractionEnabled = NO;

        // 监听按钮的点击
//        [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];
//        
//        btn.adjustsImageWhenHighlighted = NO;

        [self addSubview:btn];

    }
}

// 点击按钮的时候调用
//- (void)btnClick:(UIButton *)btn
//{
//    // 把按钮选中
//    btn.selected = YES;
//}

// 设置按钮的位置
// 只要父控件的尺寸确认,就会调用
- (void)layoutSubviews
{
    [super layoutSubviews];

    int col = 0;
    int row = 0;
    int cols = 3;
    CGFloat x = 0;
    CGFloat y = 0;
    CGFloat wh = 74;

    CGFloat margin = (self.bounds.size.width - cols * wh) / (cols + 1);

    // 布局按钮(九宫格)
    for (int i = 0; i < 9; i++) {
        UIButton *btn = self.subviews[i];
        col = i % cols;
        row = i / cols;
        x = margin + (margin + wh) * col;
        y = (margin + wh) * row;
        btn.frame = CGRectMake(x, y, wh, wh);

    }
}

@end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值