-(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); } }
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 }
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 }
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