• iOS仿安卓手势解锁


    界面是一个九宫格的布局.九宫格实现思路.
    先确定有多少列 cloum = 3;
    计算出每列之间的距离
    计算为: CGFloat margin = (当前View的宽度 - 列数 * 按钮的宽度) / 总列数 + 1
    每一列的X的值与它当前所在的行有关
    当前所在的列为:curColum = i % cloum
    每一行的Y的值与它当前所在的行有关.
    当前所在的行为:curRow = i / cloum
     
    每一个按钮的X值为, margin + 当前所在的列 * (按钮的宽度+ 每个按钮之间的间距)
    每一个按钮的Y值为 当前所在的行 * (按钮的宽度 + 每个按钮之间的距离)
     
    无论是Xib,还是代码,都做一次初始化
     

    step1:界面搭建

    -(void)awakeFromNib{
        初始化
        [self setUP];
    }
    
    -(instancetype)initWithFrame:(CGRect)frame{
        if (self = [super initWithFrame:frame]) {
             初始化
            [self setUP];
        }
        return self;
    }
    
    初始化
    - (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);
        }
    }
    

     step2:按钮选中

     1 /**
     2  *  获取当前手指所在的点
     3  *
     4  *  @param touches touches集合
     5  *
     6  *  @return 当前手指所在的点.
     7  */
     8 - (CGPoint)getCurrentPoint:(NSSet *)touches{
     9     UITouch *touch = [touches anyObject];
    10     return [touch locationInView:self];
    11 }
    12 
    13 /**
    14  *  判断一个点在不在按钮上.
    15  *
    16  *  @param point 当前点
    17  *
    18  *  @return 如果在按钮上, 返回当前按钮, 如果不在返回nil.
    19  */
    20 - (UIButton *)btnRectContainsPoint:(CGPoint)point{
    21      遍历所有的子控件
    22     for (UIButton *btn in self.subviews) {
    23          判断手指当前点在不在按钮上.
    24         if (CGRectContainsPoint(btn.frame, point)) {
    25             在按钮上.返回当前按钮
    26             return btn;
    27         }
    28     }
    29     return nil;
    30    
    31 }
    32 
    33 手指点击时让按钮成选中状态
    34 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    35 
    36     判断当前手指在不在按钮上,如果在按钮上, 让按钮成为选中状态.  
    37     1.获取当前手指所在的点
    38     CGPoint curP = [self getCurrentPoint:touches];
    39     2.判断当前手指所在的点在不在按钮上.
    40     UIButton *btn  = [self btnRectContainsPoint:curP];
    41     if (btn) {
    42         btn.selected = YES;
    43     }
    44 }
    45 
    46 手指移动时,按钮选中,连线到当前选中的按钮
    47 -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    48 
    49     判断当前手指在不在按钮上,如果在按钮上, 让按钮成为选中状态.
    50     1.获取当前手指所在的点
    51     CGPoint curP = [self getCurrentPoint:touches];
    52     2.判断当前手指所在的点在不在按钮上.
    53     UIButton *btn  = [self btnRectContainsPoint:curP];
    54     if (btn) {
    55         btn.selected = YES;
    56     }
    57 }

    step3:连线

     1 @interface ClockView()
     2 
     3 /**
     4  *  选中的按钮数组.
     5  *  每次选中一个按钮时,都把按钮添加到数组当中.移动添加到按钮当中时做一次重绘.
     6  *  重绘过程中取出所有保存的按钮, 判断是不是第一个按钮, 如果是第一个按钮,那就让它成为路径的起点.
     7  *  如果不是第一个按钮,那就添加一根线到按钮的中心点.
     8  */
     9 @property(nonatomic,strong)NSMutableArray *selectBtn;
    10 
    11 @end
    12 
    13 懒加载数组.
    14 -(NSMutableArray *)selectBtn{  
    15     if (_selectBtn == nil) {
    16         _selectBtn = [NSMutableArray array];
    17     }
    18     return _selectBtn;
    19 }
    20 
    21 手指点击时让按钮成选中状态
    22 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    23 
    24     判断当前手指在不在按钮上,如果在按钮上, 让按钮成为选中状态.
    25     1.获取当前手指所在的点
    26     CGPoint curP = [self getCurrentPoint:touches];
    27    
    28     2.判断当前手指所在的点在不在按钮上.
    29    UIButton *btn  = [self btnRectContainsPoint:curP];
    30    if (btn && btn.selected == NO) {如果按钮已经是选中状态,就不让它再添加到数组当中
    31         让按钮成为选中状态
    32         btn.selected = YES;
    33         把选中按钮添加到数组当中
    34         [self.selectBtn addObject:btn];
    35     }
    36 }
    37 
    38 手指移动时,按钮选中,连线到当前选中的按钮
    39 -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    40     判断当前手指在不在按钮上,如果在按钮上, 让按钮成为选中状态.
    41     1.获取当前手指所在的点
    42     CGPoint curP = [self getCurrentPoint:touches];
    43     2.判断当前手指所在的点在不在按钮上.
    44     UIButton *btn  = [self btnRectContainsPoint:curP];
    45     if (btn && btn.selected == NO) {//如果按钮已经是选中状态,就不让它再添加到数组当中
    46         让按钮成为选中状态
    47         btn.selected = YES;
    48         把选中按钮添加到数组当中
    49         [self.selectBtn addObject:btn];
    50         每次添加完毕后做一次重绘.
    51         [self setNeedsDisplay];
    52     }
    53 }
    54 
    55 - (void)drawRect:(CGRect)rect {
    56     创建路径.
    57     UIBezierPath *path = [UIBezierPath bezierPath];
    58     取出所有保存的选中按钮连线.
    59     for(int i = 0; i < self.selectBtn.count;i++){
    60         UIButton *btn = self.selectBtn[i];
    61         判断当前按钮是不是第一个,如果是第一个,把它的中心设置为路径的起点.
    62         if(i == 0){
    63             设置起点.
    64             [path moveToPoint:btn.center];
    65         }else{
    66             添加一根线到当前按钮的圆心.
    67             [path addLineToPoint:btn.center];
    68         }
    69     }
    70    
    71     设置颜色
    72     [[UIColor redColor] set];
    73     设置线宽
    74     [path setLineWidth:10];
    75     设置线的连接样式
    76     [path setLineJoinStyle:kCGLineJoinRound];
    77     绘制路径.
    78     [path stroke];
    79 }

    step4:业务逻辑

     1 @interface ClockView()
     2 
     3 /**
     4  *  选中的按钮数组.
     5  */
     6 @property(nonatomic,strong)NSMutableArray *selectBtn;
     7 
     8 /**
     9  *  当前手指移动的点
    10   * 记录当前手指的点,数组当中所有的点都绘制完毕后, 再添加一根线到当前手指所在的点.
    11  */
    12 @property(nonatomic,assign)CGPoint curP;
    13 
    14 @end
    15 
    16 手指松开时,按钮取消选中状态,清空所有的连线.
    17 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    18 
    19     1.取消所有选中的按钮,查看选中按钮的顺序
    20     NSMutableString *str = [NSMutableString string];
    21     for (UIButton *btn in self.selectBtn) {
    22         [str appendFormat:@"%ld",btn.tag];
    23         btn.selected = NO;
    24     }
    25     2.清空所有的连线.
    26     [self.selectBtn removeAllObjects];
    27     3.重绘
    28     [self setNeedsDisplay];
    29     NSLog(@"选中按钮顺序为:%@",str);
    30 }
    31 
    32 - (void)drawRect:(CGRect)rect {
    33     如果数组当中没有元素,就不让它进行绘图.直接返回.
    34     if(self.selectBtn.count <= 0) return;
    35     创建路径.
    36     UIBezierPath *path = [UIBezierPath bezierPath];
    37     取出所有保存的选中按钮连线.
    38     for(int i = 0; i < self.selectBtn.count;i++){
    39         UIButton *btn = self.selectBtn[i];
    40        判断当前按钮是不是第一个,如果是第一个,把它的中心设置为路径的起点.
    41         if(i == 0){
    42            设置起点.
    43             [path moveToPoint:btn.center];
    44         }else{
    45            添加一根线到当前按钮的圆心.
    46             [path addLineToPoint:btn.center];
    47         }
    48     }
    49      连完先中的按钮后, 在选中按钮之后,添加一根线到当前手指所在的点.
    50     [path addLineToPoint:self.curP];
    51      设置颜色
    52     [[UIColor redColor] set];
    53        设置线宽
    54     [path setLineWidth:10];
    55      设置线的连接样式
    56     [path setLineJoinStyle:kCGLineJoinRound];
    57      绘制路径.
    58     [path stroke];
    59 }

    github下载地址:https://github.com/CrazyZhangSanFeng/shoushijiesuo

  • 相关阅读:
    免费素材:推荐最新的免费图标字体Sosa
    如何选择Javascript模板引擎(javascript template engine)?
    名片设计最佳实践和技巧分享
    帮助你生成翻页效果的jQuery插件 bookblock
    网页网站收集
    main xml信息
    c# winrar 打包
    c# 压缩文件
    前端工程师
    fash 3D 游戏
  • 原文地址:https://www.cnblogs.com/teamblog/p/7469512.html
Copyright © 2020-2023  润新知