Sự kiện báo chí dài UIButton


86

Tôi muốn mô phỏng một nút nhấn dài, làm thế nào tôi có thể làm điều này? Tôi nghĩ rằng một bộ đếm thời gian là cần thiết. Tôi hiểu UILongPressGestureRecognizernhưng làm thế nào tôi có thể sử dụng loại này?

Câu trả lời:


160

Bạn có thể bắt đầu bằng cách tạo và đính kèm UILongPressGestureRecognizerphiên bản vào nút.

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

Và sau đó triển khai phương thức xử lý cử chỉ

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

Bây giờ đây sẽ là cách tiếp cận cơ bản. Bạn cũng có thể đặt thời lượng báo chí tối thiểu và mức độ lỗi có thể chấp nhận được. Và cũng lưu ý rằng phương thức được gọi vài lần nếu bạn sau khi nhận ra cử chỉ, vì vậy nếu bạn muốn làm điều gì đó ở cuối nó, bạn sẽ phải kiểm tra trạng thái của nó và xử lý nó.


Siêu! cảm ơn! Btw: if (gesture.state == UIGestureRecognizerStateEnded) là rất quan trọng, nếu không bạn sẽ nhận được rất nhiều sự kiện trong nhấn và giữ bạn khoảng trống
RecycleRobot

29
Bạn có thể muốn sử dụng if(gesture.state == UIGestureRecognizerStateBegan), vì người dùng mong đợi điều gì đó xảy ra khi họ vẫn đang nhấn (trạng thái Bắt đầu), chứ không phải khi họ phát hành (Đã kết thúc).
shengbinmeng

28

Để thay thế cho câu trả lời được chấp nhận, điều này có thể được thực hiện rất dễ dàng trong Xcode bằng cách sử dụng Trình tạo giao diện.

Chỉ cần kéo một Công cụ nhận dạng cử chỉ nhấn và giữ từ Thư viện đối tượng và thả nó lên đầu nút nơi bạn muốn thực hiện thao tác nhấn và giữ.

Tiếp theo, kết nối một Hành động từ Bộ nhận dạng cử chỉ báo chí dài vừa được thêm vào bộ điều khiển chế độ xem của bạn, chọn loại người gửi UILongPressGestureRecognizer. Trong mã IBActionsử dụng, mã này rất giống với mã được đề xuất trong câu trả lời được chấp nhận:

Trong Objective-C :

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

Hoặc trong Swift :

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

Nhưng tôi phải thừa nhận rằng sau khi thử nó, tôi thích đề xuất do @shengbinmeng đưa ra làm nhận xét hơn câu trả lời được chấp nhận, đó là sử dụng:

Trong Objective-C :

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

Hoặc trong Swift :

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

Sự khác biệt là với Ended, bạn thấy hiệu ứng của việc nhấn và giữ khi bạn nhấc ngón tay lên. Với Began, bạn sẽ thấy tác dụng của thao tác nhấn và giữ lâu ngay sau khi hệ thống bắt giữ thao tác nhấn dài, ngay cả trước khi bạn nhấc ngón tay ra khỏi màn hình.


18

Phiên bản Swift của câu trả lời được chấp nhận

Tôi đã thực hiện sửa đổi bổ sung về cách sử dụng UIGestureRecognizerState.Beganthay .Endedvì đó là điều mà hầu hết người dùng tự nhiên mong đợi. Tuy nhiên, hãy thử cả hai và tự mình kiểm chứng.

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")
    }
}

8

Thử đi:

Thêm nút vào viewDidLoad:như bên dưới

-(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];
}

Bây giờ gọi phương thức cử chỉ như thế này

-(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.tagcung cấp cho tôi thẻ UIButton đã nhấp sai. Bất kì giải pháp nào?
rohan-patel

3

Tôi nghĩ bạn cần giải pháp của tôi.

bạn nên có mã này cho một lần nhấn

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

đầu tiên, thêm cử chỉ nhấn và giữ vào nút

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

sau đó gọi một sự kiện báo chí liên tục nếu cử chỉ nhấn và giữ được nhận dạng.

- (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;
    }
}

Bạn không nên thêm sự kiện UIGestureRecognizertrong viewWillAppearvòng đời vì bất cứ khi nào chế độ xem xuất hiện, một trình nhận dạng cử chỉ khác sẽ được thêm vào. Điều này nên được thực hiện trong một phương thức riêng tư được gọi trong quá trình khởi tạo.
WikipediaBrown

3

Đối với Swift 4, "func longPress" cần được thay đổi để làm cho nó hoạt động:

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

Câu trả lời một dòng, không có cử chỉ:

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

Chi tiết: Điều này dẫn tới mục tiêu của bạn trên ba sự kiện: 1- Ngay lần chạm ngón tay xuống nút: UIControlEventTouchDown. Điều này bắt đầu nhấn lâu. 2 & 3- Khi người dùng nhấc ngón tay lên: UIControlEventTouchUpOutside& UIControlEventTouchUpInside. Điều này bắt đầu của người dùng nhấn.

Lưu ý: điều này hoạt động tốt nếu bạn không quan tâm đến thông tin bổ sung được cung cấp bởi trình nhận dạng cử chỉ (ví dụ: vị trí chạm, v.v.)

Bạn có thể thêm các sự kiện trung gian khác nếu cần xem tất cả chúng ở đây https://developer.apple.com/documentation/uikit/uicontrolevents?language=objc .

Trong Storyboard: Kết nối nút của bạn với 3 sự kiện, không chỉ là sự kiện mặc định mà Storyboard chọn (Touch Up Inside).

3 sự kiện trong bảng phân cảnh


0

Tôi có một UIButton phân lớp cho ứng dụng của mình, vì vậy tôi đã rút phần triển khai của mình. Bạn có thể thêm điều này vào lớp con của mình hoặc nó có thể dễ dàng được mã hóa lại như một danh mục UIButton.

Mục tiêu của tôi là thêm thao tác nhấn và giữ nút của tôi mà không làm lộn xộn bộ điều khiển chế độ xem với tất cả mã. Tôi đã quyết định rằng hành động sẽ được gọi khi trạng thái nhận dạng cử chỉ bắt đầu.

Có một cảnh báo được đưa ra mà tôi chưa bao giờ bận tâm để giải quyết. Nói rằng nó có thể bị rò rỉ, tôi nghĩ rằng tôi đã kiểm tra mã và nó không bị rò rỉ.

@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];
    }
}

Để gán hành động, hãy thêm dòng này vào phương thức viewDidLoad của bạn.

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

Hành động phải được định nghĩa giống như tất cả các IBActions (không có IBAction).

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

0

Không có tác dụng nào vì vậy tôi đã thử viết mã longpress trong IBActionhoặc nhấp vào nút từ storyboardtrong Controllerthay vì viết bằngviewDidLoad

- (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];

}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.