UI动画iOS技术点

iOS开发之手势解锁功能

2016-03-02  本文已影响1087人  李小南

如果这篇文章帮助到了您,希望您能点击一下喜欢或者评论,你们的支持是我前进的强大动力.谢谢!

首先看下我们要制作功能的效果如图所示:


手势解锁4.gif

第一步:界面搭建

在创建的UIView类中实现以下代码:

由于UIView是从storyboard中加载的,所以初始化使会调用这个方法
-(void)awakeFromNib{
    初始化 
    [self setUP];
}


初始化
- (void)setUP{
   
    for (int i = 0; i < 9;  i++) {
        添加按钮 
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 
        设置图片 
        [btn setImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal]; 
        设置选中状态的下图片 
        [btn setImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected]; 
        添加按钮 
        [self addSubview:btn];
    } 
}

布局子控件
- (void)layoutSubviews{
    [super layoutSubviews];
    总列数 
    int cloumn = 3; 
    按钮高宽
    CGFloat btnWH = 74;
    每列之间的间距 
    CGFloat margin = (self.bounds.size.width - cloumn * btnWH) / (cloumn + 1); 
    当前所在的列 
    int curClounm = 0; 
    当前所在的行 
    int curRow = 0;
    CGFloat x = 0; 
    CGFloat y = 0;
    取出所有的控件 
    for (int i = 0; i < self.subviews.count; i++) { 
        计算当前所在的列 
        curClounm = i % cloumn;
        计算当前所在的行. 
        curRow = i / cloumn;
        计算Y 
        x = margin + (margin + btnWH) * curClounm;
        计算Y. 
        y = (margin +btnWH) * curRow;
        UIButton *btn = self.subviews[i];
        btn.frame = CGRectMake(x, y, btnWH, btnWH);
    } 
}

第二步:设置按钮选中的状态

Snip20160302_7.png
/**
 *  获取当前手指所在的点
 *
 *  @param touches touches集合
 *
 *  @return 当前手指所在的点.
 */ 
- (CGPoint)getCurrentPoint:(NSSet *)touches{
    UITouch *touch = [touches anyObject];
    return [touch locationInView:self];
} 

/**
 *  判断一个点在不在按钮上.
 *
 *  @param point 当前点
 *
 *  @return 如果在按钮上, 返回当前按钮, 如果不在返回nil.
 */ 
- (UIButton *)btnRectContainsPoint:(CGPoint)point{
     遍历所有的子控件
    for (UIButton *btn in self.subviews) { 
         判断手指当前点在不在按钮上.
        if (CGRectContainsPoint(btn.frame, point)) { 
            在按钮上.返回当前按钮 
            return btn;
        }
    }
    return nil;
   
} 

手指点击时让按钮成选中状态
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 

    判断当前手指在不在按钮上,如果在按钮上, 让按钮成为选中状态. 
    (我将下面1,2两个方法按功能模块单独抽取出来.)
    1.获取当前手指所在的点 
    CGPoint curP = [self getCurrentPoint:touches]; 
    2.判断当前手指所在的点在不在按钮上.
    UIButton *btn  = [self btnRectContainsPoint:curP];
    if (btn) {
        btn.selected = YES; 
    }
}

手指移动时,按钮选中,连线到当前选中的按钮
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ 

    判断当前手指在不在按钮上,如果在按钮上, 让按钮成为选中状态. 
    1.获取当前手指所在的点 
    CGPoint curP = [self getCurrentPoint:touches]; 
    2.判断当前手指所在的点在不在按钮上. 
    UIButton *btn  = [self btnRectContainsPoint:curP];
    if (btn) {
        btn.selected = YES; 
    }
}

第三步:连线

@interface ClockView()

/**
 *  选中的按钮数组.
 *  每次选中一个按钮时,都把按钮添加到数组当中.移动添加到按钮当中时做一次重绘.
 *  重绘过程中取出所有保存的按钮, 判断是不是第一个按钮, 如果是第一个按钮,那就让它成为路径的起点.
 *  如果不是第一个按钮,那就添加一根线到按钮的中心点.
 */
@property(nonatomic,strong)NSMutableArray *selectBtn; 

@end

懒加载数组.
-(NSMutableArray *)selectBtn{  
    if (_selectBtn == nil) {
        _selectBtn = [NSMutableArray array];
    }
    return _selectBtn;
}

手指点击时让按钮成选中状态
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 

    判断当前手指在不在按钮上,如果在按钮上, 让按钮成为选中状态. 
    1.获取当前手指所在的点 
    CGPoint curP = [self getCurrentPoint:touches]; 
   
    2.判断当前手指所在的点在不在按钮上.
   UIButton *btn  = [self btnRectContainsPoint:curP]; 
   if (btn && btn.selected == NO) {如果按钮已经是选中状态,就不让它再添加到数组当中 
        让按钮成为选中状态 
        btn.selected = YES; 
        把选中按钮添加到数组当中 
        [self.selectBtn addObject:btn];
    }
} 

手指移动时,按钮选中,连线到当前选中的按钮
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ 
    判断当前手指在不在按钮上,如果在按钮上, 让按钮成为选中状态. 
    1.获取当前手指所在的点
    CGPoint curP = [self getCurrentPoint:touches]; 
    2.判断当前手指所在的点在不在按钮上. 
    UIButton *btn  = [self btnRectContainsPoint:curP]; 
    if (btn && btn.selected == NO) {//如果按钮已经是选中状态,就不让它再添加到数组当中
        让按钮成为选中状态 
        btn.selected = YES; 
        把选中按钮添加到数组当中 
        [self.selectBtn addObject:btn]; 
    }
    每次手指移动时做一次重绘. 
    [self setNeedsDisplay]; 
}

- (void)drawRect:(CGRect)rect {
    创建路径. 
    UIBezierPath *path = [UIBezierPath bezierPath];
    取出所有保存的选中按钮连线. 
    for(int i = 0; i < self.selectBtn.count;i++){
        UIButton *btn = self.selectBtn[i];
        判断当前按钮是不是第一个,如果是第一个,把它的中心设置为路径的起点. 
        if(i == 0){
            设置起点. 
            [path moveToPoint:btn.center];
        }else{
            添加一根线到当前按钮的圆心. 
            [path addLineToPoint:btn.center];
        }
    }
   
    设置颜色 
    [[UIColor redColor] set];
    设置线宽 
    [path setLineWidth:10];
    设置线的连接样式 
    [path setLineJoinStyle:kCGLineJoinRound];
    绘制路径. 
    [path stroke];
}

第四步:最后的业务逻辑

@interface ClockView() 

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

/**
 *  当前手指移动的点 
  * 记录当前手指的点,数组当中所有的点都绘制完毕后, 再添加一根线到当前手指所在的点.
 */
@property(nonatomic,assign)CGPoint curP;

@end

手指松开时,按钮取消选中状态,清空所有的连线.
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

    1.取消所有选中的按钮,查看选中按钮的顺序(根据创建按钮时绑定的tag值)
    NSMutableString *str = [NSMutableString string];
    for (UIButton *btn in self.selectBtn) {
        [str appendFormat:@"%ld",btn.tag];
        btn.selected = NO;
    }
    2.清空所有的连线.
    [self.selectBtn removeAllObjects];
    3.重绘
    [self setNeedsDisplay];
    NSLog(@"选中按钮顺序为:%@",str);
}

- (void)drawRect:(CGRect)rect {
    如果数组当中没有元素,就不让它进行绘图.直接返回. 
    if(self.selectBtn.count <= 0) return; 
    创建路径. 
    UIBezierPath *path = [UIBezierPath bezierPath]; 
    取出所有保存的选中按钮连线. 
    for(int i = 0; i < self.selectBtn.count;i++){ 
        UIButton *btn = self.selectBtn[i]; 
       判断当前按钮是不是第一个,如果是第一个,把它的中心设置为路径的起点. 
        if(i == 0){ 
           设置起点. 
            [path moveToPoint:btn.center]; 
        }else{
           添加一根线到当前按钮的圆心. 
            [path addLineToPoint:btn.center];
        } 
    }
     连完先中的按钮后, 在选中按钮之后,添加一根线到当前手指所在的点. 
    [path addLineToPoint:self.curP]; 
     设置颜色 
    [[UIColor redColor] set]; 
       设置线宽 
    [path setLineWidth:10]; 
     设置线的连接样式 
    [path setLineJoinStyle:kCGLineJoinRound]; 
     绘制路径. 
    [path stroke]; 
}

Demo已上传

地址:http://git.oschina.net/li_xiao_nan/overhand
写的不好的话忘大家指出,一起进步.谢谢!

上一篇 下一篇

猜你喜欢

热点阅读