Acara Pers Panjang UIButton

86

Saya ingin meniru tombol tekan yang lama, bagaimana cara melakukannya? Saya pikir pengatur waktu dibutuhkan. Saya mengerti UILongPressGestureRecognizertapi bagaimana saya bisa memanfaatkan tipe ini?

Andrea
sumber

Jawaban:

160

Anda dapat memulai dengan membuat dan melampirkan UILongPressGestureRecognizerinstance ke tombol.

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

Dan kemudian terapkan metode yang menangani isyarat tersebut

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

Sekarang ini akan menjadi pendekatan dasar. Anda juga dapat mengatur durasi minimum pers dan seberapa banyak kesalahan yang dapat ditoleransi. Dan juga perhatikan bahwa metode ini dipanggil beberapa kali jika Anda setelah mengenali isyarat jadi jika Anda ingin melakukan sesuatu di akhir, Anda harus memeriksa statusnya dan menanganinya.

Deepak Danduprolu
sumber
Super! Terima kasih! Btw: if (gesture.state == UIGestureRecognizerStateEnded) sangat penting, jika tidak, Anda akan mendapatkan banyak acara di longPress void
RecycleRobot
30
Anda mungkin ingin menggunakan if(gesture.state == UIGestureRecognizerStateBegan), karena pengguna mengharapkan sesuatu terjadi saat mereka masih menekan (status Dimulai), bukan saat mereka melepaskan (Berakhir).
shengbinmeng
28

Sebagai alternatif dari jawaban yang diterima, ini dapat dilakukan dengan sangat mudah di Xcode menggunakan Interface Builder.

Cukup seret Long Press Gesture Recognizer dari Object Library dan letakkan di atas tombol di mana Anda ingin aksi tekan lama.

Selanjutnya, hubungkan Action dari Long Press Gesture Recognizer yang baru saja ditambahkan, ke pengontrol tampilan Anda, pilih pengirim yang akan diketik UILongPressGestureRecognizer. Di dalam kode ituIBAction menggunakan ini, yang sangat mirip dengan kode yang disarankan dalam jawaban yang diterima:

Di Objective-C :

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

Atau di Swift :

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

Tetapi saya harus mengakui bahwa setelah mencobanya, saya lebih suka saran yang dibuat oleh @shengbinmeng sebagai komentar daripada jawaban yang diterima, yaitu menggunakan:

Di Objective-C :

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

Atau di Swift :

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

Perbedaannya adalah dengan Ended, Anda melihat efek dari tekanan lama saat Anda mengangkat jari. Dengan Began, Anda melihat efek dari penekanan lama segera setelah penekanan lama ditangkap oleh sistem, bahkan sebelum Anda mengangkat jari dari layar.

alondono.dll
sumber
18

Versi cepat dari jawaban yang diterima

Saya membuat modifikasi tambahan dengan menggunakan UIGestureRecognizerState.Begandaripada .Endedkarena itu mungkin yang diharapkan oleh sebagian besar pengguna. Cobalah keduanya dan lihat sendiri.

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")
    }
}
Suragch
sumber
10

Coba ini:

Menambahkan tombol viewDidLoad:seperti di bawah ini

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

Sekarang panggil metode isyarat seperti ini

-(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 
}
TheTiger
sumber
recognizer.view.tagmemberi saya tag salah UIButton diklik. Ada solusi?
rohan-patel
3

Saya pikir Anda membutuhkan solusi saya.

Anda harus memiliki kode ini untuk sekali tekan

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

pertama, tambahkan gerakan tekan lama ke tombol

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

kemudian panggil acara pers tunggal berulang kali jika gerakan tekan lama dikenali.

- (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;
    }
}
Jerry Juang
sumber
Anda tidak boleh menambahkan UIGestureRecognizerselama viewWillAppearacara siklus hidup karena setiap kali tampilan muncul, pengenal isyarat lain akan ditambahkan. Ini harus dilakukan dalam metode pribadi yang dipanggil selama inisialisasi.
WikipediaBrown
3

Untuk Swift 4, "func longPress" perlu diubah agar berfungsi:

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")
    }
}
Bevan
sumber
1

Jawaban satu baris, tanpa isyarat:

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

Rincian: Hal ini memicu target Anda pada tiga peristiwa: 1 Segera setelah sentuhan jari ke bawah tombol: UIControlEventTouchDown. Ini menangkap tekanan lama mulai. 2 & 3- Saat pengguna mengangkat jari ke atas: UIControlEventTouchUpOutside& UIControlEventTouchUpInside. Ini menangkap akhir pers pengguna.

Catatan: ini berfungsi dengan baik jika Anda tidak peduli dengan info tambahan yang disediakan oleh pengenal gerakan (mis. Lokasi sentuhan, dll.)

Anda dapat menambahkan lebih banyak acara perantara jika perlu, lihat semuanya di sini https://developer.apple.com/documentation/uikit/uicontrolevents?language=objc .

Di Storyboard: Hubungkan tombol Anda ke 3 peristiwa, bukan hanya yang default yang dipilih Storyboard (Touch Up Inside).

3 peristiwa di storyboard

CSawy
sumber
0

Saya memiliki UIButton subclass untuk aplikasi saya, jadi saya telah mencabut implementasi saya. Anda dapat menambahkan ini ke subkelas Anda atau ini dapat dengan mudah dikodekan ulang sebagai kategori UIButton.

Tujuan saya adalah menambahkan tekan lama ke tombol saya tanpa mengacaukan pengontrol tampilan saya dengan semua kode. Saya telah memutuskan bahwa tindakan tersebut harus dibatalkan saat status pengenal isyarat dimulai.

Ada peringatan yang keluar yang tidak pernah saya pecahkan. Mengatakan itu adalah kemungkinan kebocoran, saya pikir saya sudah menguji kodenya dan tidak bocor.

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

Untuk menetapkan tindakan, tambahkan baris ini ke metode viewDidLoad Anda.

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

Tindakan tersebut harus didefinisikan seperti semua IBAction (tanpa IBAction).

- (void)longPressAction:(id)sender {
    // sender is the button
}
Dan Loughney
sumber
0

Tidak ada yang berfungsi, maka saya mencoba menulis kode longpress IBActionatau klik tombol dari storyboarddalam Controlleralih-alih menulisviewDidLoad

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

}
karan
sumber