练习的时候做过的一个demo,附上github地址:https://github.com/H0ng/GestureLock
#HHView.h
#import <UIKit/UIKit.h>
@class HHView;
@protocol HHViewDelegate <NSObject>
@optional
-(void)showView:(HHView*)showView didFinishedPath:(NSString *)path;
@end
@interface HHView : UIView
@property (nonatomic, weak) id<HHViewDelegate> delegate;
@end
#HHView.m
#import "HHView.h"
#import "HHCircleButton.h"
@interface HHView()
@property (nonatomic, strong) NSMutableArray *totalpointPaths;
@property (nonatomic, assign) CGPoint currentPoint;
@end
@implementation HHView
-(NSMutableArray *)totalpointPaths
{
if (_totalpointPaths == nil) {
NSMutableArray *array = [NSMutableArray array];
_totalpointPaths = array;
}
return _totalpointPaths;
}
/**
* 通过代码创建会调用此方法
*/
-(instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self setup];
}
return self;
}
/**
* 通过xib,sb创建会调用此方法
*/
-(id)initWithCoder:(NSCoder *)decoder
{
if (self = [super initWithCoder:decoder]) {
[self setup];
}
return self;
}
/**
* 创建9个按钮
*/
-(void)setup
{
for (int i = 0; i < 9; i++)
{
HHCircleButton *button = [HHCircleButton buttonWithType:UIButtonTypeCustom];
button.tag = i;
[self addSubview:button];
}
}
/**
* 9个按钮的frame
*/
-(void)layoutSubviews
{
[super layoutSubviews];
for (int i = 0; i < self.subviews.count; i++) {
HHCircleButton *button = self.subviews[i];
int col = i / 3;
int row = i % 3;
CGFloat buttonW = 74;
CGFloat buttonH = 74;
CGFloat leftParading = (self.frame.size.width - buttonW * 3) / 4.0;
CGFloat buttonX = leftParading + (leftParading + buttonW) * row;
CGFloat buttonY = leftParading + (leftParading + buttonH) * col;
button.frame = CGRectMake(buttonX, buttonY, buttonW, buttonH);
}
}
#pragma mark - 返回touches点的point
-(CGPoint)pointWithTouches:(NSSet *)touches
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
return point;
}
#pragma mark - 判断触点是否在按钮的frame内
-(HHCircleButton *)buttonWithPoint:(CGPoint)point
{
for (HHCircleButton *btn in self.subviews)
{
CGFloat wh = 24;
CGFloat frameX = btn.center.x - wh * 0.5;
CGFloat frameY = btn.center.y - wh * 0.5;
if (CGRectContainsPoint(CGRectMake(frameX, frameY, wh, wh), point))
{
return btn;
}
}
return nil;
}
#pragma mark - touchesBegan
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
self.currentPoint = CGPointZero;
//获取当前触摸点
CGPoint point = [self pointWithTouches:touches];
//判断如果触摸点在某个btn上,返回这个btn,否则返回nil
HHCircleButton *btn = [self buttonWithPoint:point];
//判断是否在btn上,以及这个btn是否被选中,如果没有就选中
if (btn && btn.selected == NO) {
btn.selected = YES;
[self.totalpointPaths addObject:btn];
}
//重绘
[self setNeedsDisplay];
}
#pragma mark - touchesMoved
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint point = [self pointWithTouches:touches];
HHCircleButton *btn = [self buttonWithPoint:point];
//判断按钮是否已经被选中了
if (btn && btn.selected == NO) {
btn.selected = YES;
[self.totalpointPaths addObject:btn];
}else{
self.currentPoint = point;
}
[self setNeedsDisplay];
}
#pragma mark - touchesEnded
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// CGPoint point = [self pointWithTouches:touches];
//
// HHCircleButton *btn = [self buttonWithPoint:point];
//
// if (btn && btn.selected == NO) {
// btn.selected = YES;
// [self.totalpointPaths addObject:btn];
// }else{
// self.currentPoint = point;
// }
if ([self.delegate respondsToSelector:@selector(showView:didFinishedPath:)]) {
NSMutableString *path = [NSMutableString string];
for (HHCircleButton *btn in self.totalpointPaths) {
[path appendFormat:@"%ld",(long)btn.tag];
}
[self.delegate showView:self didFinishedPath:path];
}
//将current点清0
self.currentPoint = CGPointZero;
// //然后将所有按钮设置为非选中状态
// [self.totalpointPaths makeObjectsPerformSelector:@selector(setSelected:) withObject:@(NO)];
// [self.totalpointPaths removeAllObjects];
[self setNeedsDisplay];
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesEnded:touches withEvent:event];
}
#pragma mark - 绘制按钮间连线
-(void)drawRect:(CGRect)rect
{
if (self.totalpointPaths.count == 0) return;
UIBezierPath *path = [UIBezierPath bezierPath];
for(int index = 0; index < self.totalpointPaths.count; index++) {
HHCircleButton *btn = self.totalpointPaths[index];
if (index == 0) {
[path moveToPoint:btn.center];
}else{
[path addLineToPoint:btn.center];
}
}
if (CGPointEqualToPoint(self.currentPoint, CGPointZero) == NO) {
[path addLineToPoint:self.currentPoint];
}
path.lineWidth = 10;
path.lineJoinStyle = kCGLineJoinRound;
[[UIColor colorWithRed:32/255.0 green:210/255.0 blue:254/255.0 alpha:0.5] set];
[path stroke];
}
#HHCircleButton.h
#import <UIKit/UIKit.h>
@interface HHCircleButton : UIButton
@end
#HHCircleButton.m
#import "HHCircleButton.h"
@implementation HHCircleButton
-(id)initWithCoder:(NSCoder *)decoder
{
if (self = [super initWithCoder:decoder]) {
[self setup];
}
return self;
}
-(instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self setup];
}
return self;
}
#pragma mark - 设置按钮状态图片
-(void)setup
{
self.userInteractionEnabled = NO;
[self setBackgroundImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];
[self setBackgroundImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected];
}
@end
#ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
#ViewController.m
#import "ViewController.h"
#import "HHView.h"
@interface ViewController ()<HHViewDelegate>
//storyboard连线
@property (weak, nonatomic) IBOutlet HHView *showView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.showView.delegate = self;
}
-(void)showView:(HHView *)showView didFinishedPath:(NSString *)path
{
NSLog(@"%@",path);
}
@end