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。於是大家就能和諧相處了。