iOS开发 - 19.手势解锁

1.效果图

这里写图片描述


2.代码实现

  • 自定义View
// .m文件
#import "ZJLockView.h"
#define kBTNCOUNT 9
@interface ZJLockView ()
/**
 * 保存选中按钮
 */
@property (nonatomic, strong) NSMutableArray  *selectedBtns;
/**
 * 记录当前点位置
 */
@property (nonatomic, assign) CGPoint curP;
@end
@implementation ZJLockView

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

// 连线,将所有选中的按钮链接起来
- (void)drawRect:(CGRect)rect {
    // 若是当前数组没有值,则不重绘视图
    if (self.selectedBtns.count == 0) return;

    // 创建贝瑟尔路径
    UIBezierPath *path = [UIBezierPath bezierPath];

    // 遍历数组,连线
    for (int i = 0; i < self.selectedBtns.count; i++) {
        // 取出当前选中按钮
        UIButton *selectedBtn = self.selectedBtns[i];
        if (i == 0) { // 第一个选中按钮的中心为起始点
            [path moveToPoint:selectedBtn.center];
        }else{ // 画线
            [path addLineToPoint:selectedBtn.center];
        }
    }

    // 根据当前点的位置添加线条
    [path addLineToPoint:_curP];
    // 设置路径线宽
    path.lineWidth = 10;
    // 设置交点样式
    path.lineJoinStyle = kCGLineJoinRound;
    // 设置颜色
    [[UIColor blueColor] set];
    // 渲染路径
    [path stroke];

}

// 初始化界面
-(void)awakeFromNib{
    // 创建九个按钮
    for (int i = 0; i < kBTNCOUNT; i++) {
        // 创建按钮
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        // 设置按钮背景图片
        [btn setImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];
        // 设置选中背景图片
        [btn setImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected];
        // 设置按钮不可交互(不可点击,通过手势改变按钮状态)
        btn.userInteractionEnabled = NO;
        // 设置标记
        btn.tag = i;
        // 添加到视图上
        [self addSubview:btn];
    }
}

// 布局子控价
-(void)layoutSubviews{
    [super layoutSubviews];
    // 设置位置属性
    // 行数和列数
    int cols = 3;
    // 设置间距
    CGFloat margin = 20;
    // 计算按钮宽高
    CGFloat btnW = (self.frame.size.width - margin * (cols + 1))/ cols;
    CGFloat btnH = (self.frame.size.height - margin * (cols - 1))/ cols;
    // 取出按钮
    for (UIButton *btn in self.subviews) {
        // 确定当前按钮的行和列
        NSInteger col = btn.tag % cols;// 列
        NSInteger row = btn.tag / cols;// 行
        CGFloat btnX = margin + (btnW + margin) * col;
        CGFloat btnY = (btnH + margin) * row;
        // 设置按钮的位置
        btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
    }
}

// 监听触摸事件
// 开始触摸
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [self selectedBtn:touches withEvent:event];
}
// 触摸移动
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    // 判断是否选中按钮
    [self selectedBtn:touches withEvent:event];
    // 重绘视图
    [self setNeedsDisplay];
}
// 触摸结束
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    // 定义字符串保存当前密码
    NSMutableString *pwd = [NSMutableString string];
    // 遍历数组,设置所有按钮选中状态为NO
    for (UIButton *selBtn in self.selectedBtns) {
        selBtn.selected = NO;
        [pwd appendFormat:@"%ld",selBtn.tag];
    }
    // 打印密码
    NSLog(@"%@",pwd);

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

    // 清空线条
    [self setNeedsDisplay];
}

// 按钮选中判定
-(void)selectedBtn:(NSSet *)touches withEvent:(UIEvent *)event{
    // 获取当前点位置
    UITouch *touch = [touches anyObject];
    CGPoint curP = [touch locationInView:self];
    // 记录当前触摸点位置
    _curP = curP;
    // 转换为子控件上的位置
    for (UIButton *btn in self.subviews) {
        CGPoint subP = [self convertPoint:curP toView:btn];
        // 判断触摸点是否在当前子控件,且当前没有被选中
        if ([btn pointInside:subP withEvent:event] == YES && btn.selected == NO) { // 在当前按钮上,设置按钮为选中状态
            btn.selected = YES;
            // 将选中的按钮添加到数组中
            [self.selectedBtns addObject:btn];
        }
    }
}
@end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值