ios点击改变uiview背景颜色是一个再常见不过的需求。第一反应应该不麻烦,于是写了个第一个版本
@interface RespondentUIView() { UIColor * bgColor; } @end @implementation RespondentUIView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { bgColor = self.backgroundColor; self.backgroundColor = White_Down; } - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { self.backgroundColor = bgColor; }
@end
好像也能用。但是一会问题来了。发现touchesBegan很延时很严重的样子。于是有了第二个版本。
@interface RespondentUIView() { UIColor * bgColor; } @end @implementation RespondentUIView - (void)willMoveToSuperview:(UIView *)newSuperview { UILongPressGestureRecognizer *tapRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(changeColor:)]; tapRecognizer.minimumPressDuration = 0;//Up to you; tapRecognizer.cancelsTouchesInView = NO; [self addGestureRecognizer:tapRecognizer]; } -(void) changeColor:(UIGestureRecognizer *)gestureRecognizer{ if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { bgColor = self.backgroundColor; self.backgroundColor = White_Down; } else if (gestureRecognizer.state == UIGestureRecognizerStateEnded) { self.backgroundColor = bgColor; } } @end
用UILongPressGestureRecognizer一下子就好多了,点击反应嗖嗖的。一会又发现问题了,有的view需要注册点击事件,一个uiView注册多个UIGestureRecognizer时,总有一个不响应。真是shit。于是又google一通,发现了一个uiview使用多个
UIGestureRecognizer的方法,于是有了第三版。
@interface RespondentUIView()<UIGestureRecognizerDelegate> { UIColor * bgColor; } @end @implementation RespondentUIView - (void)willMoveToSuperview:(UIView *)newSuperview { UILongPressGestureRecognizer *tapRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(changeColor:)]; tapRecognizer.minimumPressDuration = 0;//Up to you; tapRecognizer.cancelsTouchesInView = NO; tapRecognizer.delegate = self; [self addGestureRecognizer:tapRecognizer]; } -(void) changeColor:(UIGestureRecognizer *)gestureRecognizer{ if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { bgColor = self.backgroundColor; self.backgroundColor = White_Down; } else if (gestureRecognizer.state == UIGestureRecognizerStateEnded) { self.backgroundColor = bgColor; } } //下面三个函数用于多个GestureRecognizer 协同作业,避免按下的手势影响了而别的手势不响应 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { return YES; } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { return YES; } @end
这下感觉整个世界清静了。顺带提一下
tapRecognizer.cancelsTouchesInView = NO;
这是一个很犀利的属性。一般ios响应链传递的顺序是先交给UIView的UIGestureRecognizer处理。如果它处理了,就把事件丢掉了,于是UIView上面的touchesBegan和touchesEnded等优先级比较低的UIResponder就没机会响应了。把cancelsTouchesInView置为NO。于是大家就能和谐相处了。