UIButton Long Press Event


86

ฉันต้องการเลียนแบบการกดปุ่มแบบยาวฉันจะทำได้อย่างไร? ฉันคิดว่าต้องใช้ตัวจับเวลา ฉันเห็นUILongPressGestureRecognizerแต่ฉันจะใช้ประโยชน์จากประเภทนี้ได้อย่างไร?

คำตอบ:


160

คุณสามารถเริ่มต้นได้ด้วยการสร้างและติดUILongPressGestureRecognizerอินสแตนซ์เข้ากับปุ่ม

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[self.button addGestureRecognizer:longPress];
[longPress release];

จากนั้นใช้วิธีการที่จัดการกับท่าทาง

- (void)longPress:(UILongPressGestureRecognizer*)gesture {
    if ( gesture.state == UIGestureRecognizerStateEnded ) {
         NSLog(@"Long Press");
    }
}

ตอนนี้จะเป็นแนวทางพื้นฐาน คุณยังสามารถกำหนดระยะเวลาขั้นต่ำของการกดและความผิดพลาดที่ยอมรับได้ และโปรดทราบว่าวิธีนี้ถูกเรียกไม่กี่ครั้งหากคุณจำท่าทางได้แล้วดังนั้นหากคุณต้องการทำอะไรบางอย่างในตอนท้ายคุณจะต้องตรวจสอบสถานะและจัดการกับมัน


สุดยอด! ขอบคุณ! Btw: if (Gesture.state == UIGestureRecognizerStateEnded) มีความสำคัญมากมิฉะนั้นคุณจะได้รับเหตุการณ์มากมายใน longPress void ของคุณ
RecycleRobot

30
คุณอาจต้องการใช้if(gesture.state == UIGestureRecognizerStateBegan)เนื่องจากผู้ใช้คาดว่าจะมีบางอย่างเกิดขึ้นเมื่อพวกเขายังคงกดอยู่ (สถานะเริ่มต้น) ไม่ใช่เมื่อพวกเขาปล่อย (สิ้นสุด)
shengbinmeng

28

เป็นอีกทางเลือกหนึ่งของคำตอบที่ได้รับการยอมรับสามารถทำได้อย่างง่ายดายใน Xcode โดยใช้ Interface Builder

เพียงลากLong Press Gesture RecognizerจากObject Libraryแล้ววางไว้ที่ด้านบนของปุ่มที่คุณต้องการให้กดแบบยาว

ต่อมาเชื่อมต่อการกระทำจากลองกดท่าทางลายมือUILongPressGestureRecognizerเพิ่งเพิ่มไปยังตัวควบคุมมุมมองของคุณเลือกผู้ส่งจะเป็นประเภท ในรหัสนั้นIBActionใช้สิ่งนี้ซึ่งคล้ายกับรหัสที่แนะนำในคำตอบที่ยอมรับ:

ในObjective-C :

if ( sender.state == UIGestureRecognizerStateEnded ) {
     // Do your stuff here
}

หรือในSwift :

if sender.state == .Ended {
    // Do your stuff here
}

แต่ฉันต้องยอมรับว่าหลังจากลองใช้แล้วฉันชอบคำแนะนำของ @shengbinmeng เป็นความคิดเห็นสำหรับคำตอบที่ยอมรับซึ่งใช้:

ในObjective-C :

if ( sender.state == UIGestureRecognizerStateBegan ) {
     // Do your stuff here
}

หรือในSwift :

if sender.state == .Began {
    // Do your stuff here
}

ความแตกต่างก็คือEndedคุณจะเห็นผลของการกดแบบยาวเมื่อคุณยกนิ้วขึ้น ด้วยBeganคุณจะเห็นผลของการกดแบบยาวทันทีที่ระบบจับการกดแบบยาวก่อนที่คุณจะยกนิ้วออกจากหน้าจอ


18

คำตอบที่ยอมรับเวอร์ชัน Swift

ฉันได้ทำการปรับเปลี่ยนการใช้งานเพิ่มเติมUIGestureRecognizerState.Beganแทนที่จะเป็น.Endedเพราะนั่นอาจเป็นสิ่งที่ผู้ใช้ส่วนใหญ่คาดหวังโดยธรรมชาติ ลองทั้งสองอย่างและดูด้วยตัวคุณเอง

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var button: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // add gesture recognizer
        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(_:)))
        self.button.addGestureRecognizer(longPress)
        
    }

    func longPress(gesture: UILongPressGestureRecognizer) {
        if gesture.state == UIGestureRecognizerState.began {
            print("Long Press")
        }
    }
    
    @IBAction func normalButtonTap(sender: UIButton) {
        print("Button tapped")
    }
}

10

ลองสิ่งนี้:

กำลังเพิ่มปุ่มviewDidLoad:เหมือนด้านล่าง

-(void)viewDidLoad {
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [btn setTag:1]; //you can set any integer value as tag number
    btn.title = @"Press Me";
    [btn setFrame:CGRectMake(50.0, 50.0, 60.0, 60.0)];

    // now create a long press gesture
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressTap:)];
    [btn addGestureRecognizer:longPress];
}

ตอนนี้เรียกวิธีการแสดงท่าทางเช่นนี้

-(void)longPressTap:(id)sender {
     UIGestureRecognizer *recognizer = (UIGestureRecognizer*) sender
    // Recogniser have all property of button on which you have clicked
    // Now you can compare button's tag with recogniser's view.tag  
    // View frame for getting the info on which button the click event happened 
    // Then compare tag like this
    if(recognizer.view.tag == 1) { 
       // Put your button's click code here
    }

    // And you can also compare the frame of your button with recogniser's view
    CGRect btnRect = CGRectMake(50.0, 50.0, 60.0, 60.0);
    if(recogniser.view.frame == btnRect) {
       //put your button's click code here
    }

   // Remember frame comparing is alternative method you don't need  to write frame comparing code if you are matching the tag number of button 
}

recognizer.view.tagทำให้ฉันมีแท็ก UIButton ที่ไม่ถูกต้อง วิธีแก้ปัญหาใด ๆ
rohan-patel

3

ฉันคิดว่าคุณต้องการทางออกของฉัน

คุณควรมีรหัสนี้สำหรับการกดเพียงครั้งเดียว

- (IBAction)buttonDidPress:(id)sender {
    NSLog("buttonDidPress");
}

ขั้นแรกให้เพิ่มท่าทางการกดแบบยาวที่ปุ่ม

- (void)viewWillAppear:(BOOL)animated
{
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(buttonDidLongPress:)];
    [self.button addGestureRecognizer:longPress];
}

จากนั้นเรียกเหตุการณ์กดครั้งเดียวซ้ำ ๆ หากจำท่าทางการกดแบบยาวได้

- (void)buttonDidLongPress:(UILongPressGestureRecognizer*)gesture
{
    switch (gesture.state) {
        case UIGestureRecognizerStateBegan:
        {
            self.timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(buttonDidPress:) userInfo:nil repeats:YES];

            NSRunLoop * theRunLoop = [NSRunLoop currentRunLoop];
            [theRunLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
        }
            break;
        case UIGestureRecognizerStateEnded:
        {
            [self.timer invalidate];
            self.timer = nil;
        }
            break;
        default:
            break;
    }
}

คุณไม่ควรเพิ่มเหตุการณ์UIGestureRecognizerในช่วงอายุการviewWillAppearใช้งานเนื่องจากเมื่อใดก็ตามที่มุมมองปรากฏขึ้นระบบจะเพิ่มตัวจดจำท่าทางอื่น สิ่งนี้ควรทำในเมธอดส่วนตัวที่เรียกระหว่างการเริ่มต้น
WikipediaBrown

3

สำหรับ Swift 4 จำเป็นต้องเปลี่ยน "func longPress" เพื่อให้ใช้งานได้:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var button: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        // add guesture recognizer
        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(_:)))
        self.button.addGestureRecognizer(longPress)

    }

   @objc func longPress(_ guesture: UILongPressGestureRecognizer) {
        if guesture.state == UIGestureRecognizerState.began {
            print("Long Press")
        }
    }

    @IBAction func normalButtonTap(sender: UIButton) {
        print("Button tapped")
    }
}

1

คำตอบหนึ่งบรรทัดโดยไม่มีท่าทาง:

[btn addTarget:self action:@selector(handleTouch:) forControlEvents:UIControlEventTouchDown | UIControlEventTouchUpInside | UIControlEventTouchUpOutside];

รายละเอียด: นี้จะเรียกเป้าหมายของคุณในสามเหตุการณ์: 1- UIControlEventTouchDownทันทีเมื่อสัมผัสนิ้วลงปุ่ม: สิ่งนี้จับการกดแบบยาว 2 & 3- เมื่อผู้ใช้ยกนิ้วขึ้น: UIControlEventTouchUpOutside& UIControlEventTouchUpInside. สิ่งนี้จับจุดสิ้นสุดของการกดของผู้ใช้

หมายเหตุ: ใช้งานได้ดีหากคุณไม่สนใจข้อมูลเพิ่มเติมที่มาจากเครื่องมือจดจำท่าทาง (เช่นตำแหน่งของการสัมผัส ฯลฯ )

คุณสามารถเพิ่มกิจกรรมกลางเพิ่มเติมถ้าจำเป็นเห็นพวกเขาทั้งหมดที่นี่https://developer.apple.com/documentation/uikit/uicontrolevents?language=objc

ใน Storyboard: เชื่อมต่อปุ่มของคุณกับ 3 เหตุการณ์ไม่ใช่แค่ค่าเริ่มต้นที่ Storyboard เลือก (Touch Up Inside)

3 เหตุการณ์ในสตอรีบอร์ด


0

ฉันมี UIButton คลาสย่อยสำหรับแอปของฉันดังนั้นฉันจึงดึงการใช้งานออกมา คุณสามารถเพิ่มสิ่งนี้ลงในคลาสย่อยของคุณหรือสามารถเข้ารหัสเป็นหมวดหมู่ UIButton ได้อย่างง่ายดาย

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

มีคำเตือนออกมาว่าไม่เคยใส่ใจที่จะแก้ บอกว่ามันอาจจะรั่วคิดว่าฉันทดสอบโค้ดแล้วและมันไม่รั่ว

@interface MYLongButton ()
@property (nonatomic, strong) UILongPressGestureRecognizer *gestureRecognizer;
@property (nonatomic, strong) id gestureRecognizerTarget;
@property (nonatomic, assign) SEL gestureRecognizerSelector;
@end

@implementation MYLongButton

- (void)addLongPressTarget:(CGFloat)interval target:(id)target action:(SEL)selector
{
    _gestureRecognizerTarget = target;
    _gestureRecognizerSelector = selector;
    _gestureRecognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleLongPressGestureRecognizer:)];
    _gestureRecognizer.minimumPressDuration = interval;

    [self addGestureRecognizer:_gestureRecognizer];
}

- (void)handleLongPressGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        NSAssert([_gestureRecognizerTarget respondsToSelector:_gestureRecognizerSelector], @"target does not respond to selector");

        self.highlighted = NO;

        // warning on possible leak -- can anybody fix it?
        [_gestureRecognizerTarget performSelector:_gestureRecognizerSelector withObject:self];
    }
}

หากต้องการกำหนดการดำเนินการให้เพิ่มบรรทัดนี้ในเมธอด viewDidLoad ของคุณ

[_myLongButton addLongPressTarget:0.75 target:self selector:@selector(longPressAction:)];

ควรกำหนดการกระทำเช่นเดียวกับ IBActions ทั้งหมด (ไม่มี IBAction)

- (void)longPressAction:(id)sender {
    // sender is the button
}

0

ไม่ได้ผลดังนั้นฉันจึงลองเขียนโค้ด longpress IBActionหรือคลิกปุ่มจากstoryboardในControllerแทนการเขียนviewDidLoad

- (IBAction)btnClick:(id)sender {

    tag = (int)((UIButton *)sender).tag;

// Long press here instead of in viewDidLoad

    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
    longPress.cancelsTouchesInView = NO;
    [sender addGestureRecognizer:longPress];

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.