เครื่องมือจดจำท่าทางและการทำงานของปุ่ม


99

ฉันมีลำดับชั้นการดูที่มีลักษณะดังนี้:

UIView (A)
UIView > UIImageView
UIView > UIView (B)
UIView > UIView (B) > Rounded Rect Button
UIView > UIView (B) > UIImageView
UIView > UIView (B) > UILabel

ฉันได้แนบเครื่องมือจดจำท่าทางกับ UIView (B) ของฉันแล้ว ปัญหาที่ฉันเผชิญคือฉันไม่ได้รับการดำเนินการใด ๆ สำหรับปุ่ม Rounded Rect ที่อยู่ใน UIView (B) ระบบจดจำท่าทางสัมผัส singleTap จับ / แทนที่เหตุการณ์ 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;
    }
}

วิธีที่ง่ายที่สุดคือตั้งค่า cancelsTouchesInView = false
Bagusflyer

คำตอบ:


176

ในเมธอด "shouldReceiveTouch" คุณควรเพิ่มเงื่อนไขที่จะคืนค่า NO หากการสัมผัสอยู่ในปุ่ม

นี่มาจากตัวอย่างSimpleGestureRecognizers ของ apple

- (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ให้ได้ผล

shani


1
อา!!! ใช่ฉันลืมเกี่ยวกับวิธีนี้ -gestureRecognizer: shouldReceiveTouch: ขอขอบคุณที่ชี้ทางที่ถูกต้องให้ฉัน แม้ว่าสิ่งนี้จะช่วยแก้ปัญหาของฉันได้ แต่ฉันก็ยังไม่รู้ว่าทำไมลำดับชั้นของผู้ตอบกลับไม่ทำงานในกรณีนี้ อาจเป็นไปได้ แต่ Apple ไม่ได้รับการจัดการ
มุสตาฟา

2
ลักษณะการทำงานของ UIGestureRecognizer อธิบายไว้อย่างชัดเจนว่าแยกจากห่วงโซ่การตอบกลับ "ปกติ" นี่เป็นการตัดสินใจออกแบบโดย Apple
Sylvain G.

11
อย่าลืมปฏิบัติตาม UIGestureRecognizerDelegate Protocol และตั้งค่าผู้รับมอบสิทธิ์ของ UIGestureRecognizer ให้กับวัตถุนั้น
Daniel

2
สำหรับการใช้งานที่กว้างขึ้นให้พิจารณาตัวแปรบางอย่างในข้อทดสอบของ Ramesh หรือ flypig ในกรณีของฉันฉันลงเอยด้วยบรรทัด: if ( [touch.view isKindOfClass:[UIControl class]] || [[touch.view superview] isKindOfClass:[UITableViewCell class]] ) {... โปรดทราบว่าเซลล์ tableview ได้รับการ "สัมผัส" ใน contentView ซึ่งเป็นสมาชิกของคลาสส่วนตัวดังนั้นเราจึงตรวจสอบคลาสของ superview แทน
clozach

ขอบคุณสำหรับคำตอบ! ในกรณีของฉันฉันพบปัญหาเดียวกัน แต่ฉันค้นพบจนกว่าจะได้ทดสอบในอุปกรณ์จริงเท่านั้น การเรียกใช้แอปในโปรแกรมจำลองโดยไม่ใช้ UIGestureDelegate ตามที่ระบุในคำตอบนี้ทำงานได้ตามที่คาดไว้แม้ว่าจะไม่ถูกต้อง
Luis Artola

51

ฉันก็มีปัญหาเดียวกันจากนั้นฉันก็ลองใช้

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{

    if ([touch.view isKindOfClass:[UIButton class]]) {      //change it to your condition
        return NO;
    }
    return YES;
}

ตอนนี้ทำงานได้อย่างสมบูรณ์แบบ .........


4
ฉันพลาดmyGestureRecognizer.delegate = self;
zero3nna

20

โดยทั่วไปเราใช้วิธีการมอบหมายด้านล่างเพื่อหลีกเลี่ยงการสัมผัสใน UIControls ทุกประเภท:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if (([touch.view isKindOfClass:[UIControl class]])) {
         return NO;
    }
    return YES;
}

หมายเหตุ: อย่าทำการตรวจสอบนี้ (ตรวจสอบประเภทคลาสของโปรแกรมรับรู้การดู) การใช้งานท่าทางRecognizerShouldBeginจะไม่ทำงาน


11

นี่คือเวอร์ชันSwift 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)


6

นี่คือเวอร์ชัน Swift:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if (touch.view!.isKindOfClass(UIButton)) {
        return false
    }
    return true
}

อย่าลืม:

  1. ทำให้ชั้นเรียนของคุณเป็นไปตาม UIGestureRecognizerDelegate
  2. ทำให้ผู้ร่วมประชุมกรีดวัตถุของคุณด้วยตนเอง (เช่นtapper.delegate = self)

5

ทางออกที่ดีที่สุดคือการใช้ข้อมูลโค้ดด้านล่าง:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    CGPoint touchLocation = [touch locationInView:self.view];
    return !CGRectContainsPoint(self.menuButton.frame, touchLocation);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.