iOS开发核心动画之九宫格解锁
一. 九宫格解锁
1. 自定义一个View,初始化子控件,创建九个按钮
// 从xib中加载时调用
- (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];
btn.userInteractionEnabled = NO;
btn.tag = i;
}
}
2. 设置frame
// 子控件设置frame
- (void)layoutSubviews
{
[super layoutSubviews];
int rowNum = 3;
CGFloat line = 0;
CGFloat row = 0;
CGFloat btnHW = 74;
CGFloat space = (self.bounds.size.width - btnHW * 3) / (rowNum + 1);
for (int i = 0; i < self.subviews.count; ++i) {
UIButton *btn = self.subviews[i];
row = i / rowNum;
line = i % rowNum;
CGFloat btnX = space + line * (space + btnHW);
CGFloat btnY = row * (space + btnHW);
btn.frame = CGRectMake(btnX, btnY, btnHW, btnHW);
}
}
3. 监听开始触摸,判断当前触摸点是否在按钮上,如果在设置为选中状态并记录,将选中的按钮添加到一个数组中保存
// 获取当前触摸点
- (CGPoint)getCurrentPointWithSet:(NSSet *)touches
{
// 1.获取触摸对象
UITouch *touch = [touches anyObject];
// 2.获取当前的触摸点
return [touch locationInView:self];
}
// 判断当前触摸点是否在按钮上
- (UIButton *)getButtonWithPoint:(CGPoint)point
{
// 3.判断当前点是否在按钮上
for (UIButton *btn in self.subviews) {
if (CGRectContainsPoint(btn.frame, point) && btn.selected == NO) {
[self.selectedBtnArray addObject:btn];
return btn;
}
}
return nil;
}
// 开始触摸
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 获取当前触摸点
CGPoint curP = [self getCurrentPointWithSet:touches];
// 3.判断当前点是否在按钮上
UIButton *btn = [self getButtonWithPoint:curP];
if (btn) {
btn.selected = YES;
self.startBtn = btn;
}
}
4. 监听触摸移动,同样判断触摸点是否在按钮上,如果在则设置为选中状态并添加到数组中保存
重绘
// 移动触摸
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// 获取当前触摸点
CGPoint curP = [self getCurrentPointWithSet:touches];
self.curP = curP;
// 3.判断当前点是否在按钮上
UIButton *btn = [self getButtonWithPoint:curP];
if (btn) {
btn.selected = YES;
}
// 重绘
[self setNeedsDisplay];
}
5. 绘制数组中的按钮
- (void)drawRect:(CGRect)rect {
UIBezierPath *path = [UIBezierPath bezierPath];
if (self.selectedBtnArray.count) {
for (int i = 0; i < self.selectedBtnArray.count; ++i) {
UIButton *btn = self.selectedBtnArray[i];
if (i == 0) {
[path moveToPoint:self.startBtn.center];
} else {
[path addLineToPoint:btn.center];
}
}
[[UIColor redColor] set];
[path setLineWidth:10];
[path setLineJoinStyle:kCGLineJoinRound];
[path setLineCapStyle:kCGLineCapRound];
[path addLineToPoint:self.curP];
[path stroke];
}
}
6. 停止触摸时将按钮选中状态取消,并重绘
// 停止触摸
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSMutableString *strM = [NSMutableString string];
// 1.将选中按钮取消选中状态
for (UIButton *btn in self.selectedBtnArray) {
btn.selected = NO;
[strM appendFormat:@"%zd", btn.tag];
}
// 2.清空选中按钮数组
[self.selectedBtnArray removeAllObjects];
// 3.重绘
[self setNeedsDisplay];
NSLog(@"%@", strM);
// 4.将密码发给控制器判断密码是否登录
if ([self.delegate respondsToSelector:@selector(lockView:loginToStr:)]) {
[self.delegate lockView:self loginToStr:strM];
}
}