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/shoushijiesuonode

相關文章
相關標籤/搜索