제스처 인식기 및 버튼 동작
보기 계층 구조는 다음과 같습니다.
UIView (A)
UIView > UIImageView
UIView > UIView (B)
UIView > UIView (B) > Rounded Rect Button
UIView > UIView (B) > UIImageView
UIView > UIView (B) > UILabel
UIView(B)에 제스처 인식기를 첨부했습니다.제가 직면한 문제는 UIView(B) 내부에 있는 Rounded Rect Button에 대한 어떠한 조치도 받지 않는다는 것입니다.단일 Tap 제스처 인식기는 버튼의 Touch Up Inside 이벤트를 캡처/ 덮어씁니다.
어떻게 하면 될 수 있을까요?나는 응답자 체인 계층 구조가 버튼 터치 이벤트에 우선권을 부여하고 트리거 될 것이라고 생각했습니다!제가 무엇을 빠뜨리고 있나요?
관련 코드는 다음과 같습니다.
#pragma mark -
#pragma mark View lifecycle (Gesture recognizer setup)
- (void)viewDidLoad {
[super viewDidLoad];
// double tap gesture recognizer
UITapGestureRecognizer *dtapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapGestureRecognizer:)];
dtapGestureRecognize.delegate = self;
dtapGestureRecognize.numberOfTapsRequired = 2;
[self.viewB addGestureRecognizer:dtapGestureRecognize];
// single tap gesture recognizer
UITapGestureRecognizer *tapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureRecognizer:)];
tapGestureRecognize.delegate = self;
tapGestureRecognize.numberOfTapsRequired = 1;
[tapGestureRecognize requireGestureRecognizerToFail:dtapGestureRecognize];
[self.viewB addGestureRecognizer:tapGestureRecognize];
// add gesture recodgnizer to the grid view to start the edit mode
UILongPressGestureRecognizer *pahGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognizerStateChanged:)];
pahGestureRecognizer.delegate = self;
pahGestureRecognizer.minimumPressDuration = 0.5;
[self.viewB addGestureRecognizer:pahGestureRecognizer];
[dtapGestureRecognize release];
[tapGestureRecognize release];
[pahGestureRecognizer release];
}
#pragma mark -
#pragma mark Button actions
- (IBAction)buttonTouchUpInside:(id)sender {
NSLog(@"%s, %@", __FUNCTION__, sender);
}
#pragma mark -
#pragma mark Gesture recognizer actions
- (void)singleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
NSLog(@"%s", __FUNCTION__);
}
- (void)doubleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
NSLog(@"%s", __FUNCTION__);
}
- (void)longPressGestureRecognizerStateChanged:(UIGestureRecognizer *)gestureRecognizer {
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateEnded: {
NSLog(@"%s", __FUNCTION__);
break;
}
default:
break;
}
}
"should receiveTouch" 방법에서는 터치가 버튼에 있으면 NO를 반환하는 조건을 추가해야 합니다.
이는 Apple Simple Gesture Recognizers 예제에서 가져온 것입니다.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// Disallow recognition of tap gestures in the segmented control.
if ((touch.view == yourButton)) {//change it to your condition
return NO;
}
return YES;
}
도움이 되기를 바랍니다
편집
다니엘이 언급한 것처럼, 당신은 당신이 해야만 합니다.UIGestureRecognizerDelegate
그것이 작동하기 위해서요.
샤니
저도 같은 문제가 있었는데, 그 다음에 시도했습니다.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
if ([touch.view isKindOfClass:[UIButton class]]) { //change it to your condition
return NO;
}
return YES;
}
지금은 완벽하게 작동하고 있습니다......
일반적으로 모든 종류의 UIC 컨트롤에서 접촉을 피하기 위해 아래 딜러 방법을 사용합니다.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if (([touch.view isKindOfClass:[UIControl class]])) {
return NO;
}
return YES;
}
참고: 이 확인을 수행하지 마십시오(recognizer.view class type 확인) 제스처 RecognizerShouldBegin, 작동하지 않습니다.
스위프트 3.0 버전은 다음과 같습니다.
extension UIViewController: UIGestureRecognizerDelegate {
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if touch.view is UIButton {
return false
}
return true
}
잊지 마십시오.
Make your tapper object delegate to self (e.g: tapper.delegate = self)
가장 좋은 해결책은 아래의 코드 조각을 사용하는 것입니다.
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
CGPoint touchLocation = [touch locationInView:self.view];
return !CGRectContainsPoint(self.menuButton.frame, touchLocation);
}
스위프트 버전은 다음과 같습니다.
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if (touch.view!.isKindOfClass(UIButton)) {
return false
}
return true
}
잊지 마십시오.
- 당신의 수업을 따르도록 합니다.
UIGestureRecognizerDelegate
- 태퍼 오브젝트를 스스로에게 위임합니다(예:
tapper.delegate = self
)
대리인 내부의 Swift 5의 경우 다음을 추가할 수 있습니다.
return (touch.view is UIButton) ? false : true
비비안의 빠른 답변:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
let location = touch.location(in: view)
return !someView.frame.contains(location)
}
제 경우는 다음과 같습니다.
UIView (with tap gesture)
├-> UIView (named "textFieldView")
├-> UIControl
├-> UITextField
├-> UIView (over the textField, with a tap gesture)
╭──────────────────────────────╮
│ ╭──────────────────────────╮ │
│ │ ╭──╮ ┌╴╶╴╶╴╶╴╶╴╶╴╶╴╶╴╶┐ │ │
│ │ ╰──╯ └╴╶╴╶╴╶╴╶╴╶╴╶╴╶╴╶┘ │ │
│ ╰──────────────────────────╯ │
└──────────────────────────────┘
UIView 위쪽의 TapGesture가 UI Control target과 충돌을 일으키고 있습니다.대상이 다음과 같이 설정된 경우 대상이 호출되었습니다.touchDown
(그러나 호출되지 않음)touchUpInside
) 또는 상속을 다음에서 변경하는 경우UIControl
로.UIButton
이벤트에 대한 대상 설정을 유지하면서touchUpInside
.
이 문제를 해결하기 위해 제가 하는 일은 탭 제스처의 대리인으로 상부 보기를 설정하는 것입니다.기능.func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool
(UIView 상단에) 다음과 같이 구현됩니다.
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
let touchLocationRelatedToTextFieldView = touch.location(in: textFieldView)
return textFieldView.frame.contains(touchLocationRelatedToTextFieldView) == false
}
딜러 기능을 구현하면 UIC 컨트롤 및 대상 설정을 계속 실행할 수 있습니다.touchUpInside
! :)
언급URL : https://stackoverflow.com/questions/4825199/gesture-recognizer-and-button-actions
'source' 카테고리의 다른 글
무슨 일이 있어도 최대 절전 모드에서 MySQL INSERT 문을 배치할 수 없습니다. (0) | 2023.10.03 |
---|---|
SQL 디코딩 Null 값 (0) | 2023.10.03 |
MySQL에서 COUNT(id) 대 COUNT(*) (0) | 2023.10.03 |
MVC 어플리케이션에서 데이터를 캐시하는 방법 (0) | 2023.10.03 |
HTTP Put은 어떻게 합니까? (0) | 2023.10.03 |