UITableView'a uzun basın


Yanıtlar:


427

İlk önce uzun basma hareketi tanıyıcıyı tablo görünümüne ekleyin:

UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc] 
  initWithTarget:self action:@selector(handleLongPress:)];
lpgr.minimumPressDuration = 2.0; //seconds
lpgr.delegate = self;
[self.myTableView addGestureRecognizer:lpgr];
[lpgr release];

Sonra hareket işleyicisinde:

-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
    CGPoint p = [gestureRecognizer locationInView:self.myTableView];

    NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:p];
    if (indexPath == nil) {
        NSLog(@"long press on table view but not on a row");
    } else if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        NSLog(@"long press on table view at row %ld", indexPath.row);
    } else {
        NSLog(@"gestureRecognizer.state = %ld", gestureRecognizer.state);
    }
}

Kullanıcının hücrenin normal dokunuşuna müdahale etmemesi ve aynı zamanda handleLongPressbirden fazla ateşlenebileceğini unutmayın (bu, hareket tanıma durumu değişikliklerinden kaynaklanacaktır) buna dikkat etmelisiniz .


1
Müthiş !!! Çok teşekkürler! Ama son bir soru: TouchLongPress yöntemi neden dokunmatik bittiğinde çağrılıyor ???
FoOg

111
Düzeltme: jestin farklı durumlarını (başladı, değişti, sona erdi, vb.) Belirtmek için birkaç kez ateşler. Dolayısıyla, işleyici yönteminde, hareketin her durumunda eylem yapmaktan kaçınmak için hareket tanıyıcısının state özelliğini kontrol edin. Ör: if (gestureRecognizer.state == UIGestureRecognizerStateBegan) ....

3
Bu cevap ;-) daha kolaydır böylece unutma, jest tanıyıcıları artık Interface Builder doğrudan UI öğeleri eklendi ve IBAction yöntemle bağlanabilir (sadece için tanıyıcı takmak için hatırlamak UITableViewdeğil UITableViewCell...)

10
Ayrıca class.h dosyasındaki UIGestureRecognizerDelegate protokolüne onaylayın
Vaquita

1
Tablo görünümünün hücreye gitmesini nasıl önlersiniz ('didSelectRowAtIndexPath' uyguladıysanız)
17'de

46

Anna-Karenina'nın cevabını kullandım ve çok ciddi bir hata ile neredeyse harika çalışıyor.

Bölümler kullanıyorsanız, bölüm başlığına uzun süre basmak size bu bölümdeki ilk satıra basmanın yanlış bir sonucunu verecektir, aşağıya sabit bir sürüm ekledim (hareket durumuna göre kukla çağrıların filtrelenmesi dahil, Anna-Karenina önerisi).

- (IBAction)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {

        CGPoint p = [gestureRecognizer locationInView:self.tableView];

        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
        if (indexPath == nil) {
            NSLog(@"long press on table view but not on a row");
        } else {
            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
            if (cell.isHighlighted) {
                NSLog(@"long press on table view at section %d row %d", indexPath.section, indexPath.row);
            }
        }
    }
}

Merhaba @marmor: Bir görünümün hangi kullanıcının dokunduğu sadece bir kısmını tanımlamak mümkün mü sormak istiyorum?
Manthan

Hey, bunun için hitTest kullanabilirsiniz ( developer.apple.com/library/ios/documentation/uikit/reference/… ). Örneğin nasıl kullanılacağına ilişkin bu yanıtı kontrol edin: stackoverflow.com/a/2793253/819355
marmor

Kabul edilen cevap çalışırken. Ekranda sürüklerken günlüğe kaydetme ile birlikte çoklu yangınları günlüğe kaydeder. Bu cevap yok. Yasal bir kopyala yapıştır yanıtı. Teşekkür ederim.
ChrisOSX

29

Swift 5'teki cevap (Ricky'nin Swift'teki cevabının devamı)

UIGestureRecognizerDelegateViewController'ınıza ekleyin

 override func viewDidLoad() {
    super.viewDidLoad()

    //Long Press
    let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
    longPressGesture.minimumPressDuration = 0.5
    self.tableView.addGestureRecognizer(longPressGesture)
 }

Ve fonksiyon:

@objc func handleLongPress(longPressGesture: UILongPressGestureRecognizer) {
    let p = longPressGesture.location(in: self.tableView)
    let indexPath = self.tableView.indexPathForRow(at: p)
    if indexPath == nil {
        print("Long press on table view, not row.")
    } else if longPressGesture.state == UIGestureRecognizer.State.began {
        print("Long press on row, at \(indexPath!.row)")
    }
}

20

İşte Dawn Song'un cevabı ile Marmor'un cevabını birleştiren net talimat.

Uzun bir Basın Hareket Tanıyıcısını sürükleyin ve Tablo Hücrenize bırakın. Soldaki listenin altına atlayacaktır.

resim açıklamasını buraya girin

Ardından hareket tanımlayıcıyı bir düğmeyi bağladığınız şekilde bağlayın. resim açıklamasını buraya girin

Eylem işleyicisine Marmor kodunu ekleyin

- (IBAction)handleLongPress:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {

    CGPoint p = [sender locationInView:self.tableView];

    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
    if (indexPath == nil) {
        NSLog(@"long press on table view but not on a row");
    } else {
        UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
        if (cell.isHighlighted) {
            NSLog(@"long press on table view at section %d row %d", indexPath.section, indexPath.row);
        }
    }
}

}


2
Bence en iyi cevap
Asen Kasimov

8
Uzun Basın Hareket Tanıyıcı tablo görünümü hücresine değil tablo görünümüne uygulanmalıdır. Tablo görünümü hücresine düşürüldüğünde yalnızca satır 0 uzun basmayı dinleyecektir.
Alex


11

Swift içinde cevap:

UIGestureRecognizerDelegateUITableViewController'ınıza temsilci ekleyin .

UITableViewController içinde:

override func viewDidLoad() {
    super.viewDidLoad()

    let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleLongPress:")
    longPressGesture.minimumPressDuration = 1.0 // 1 second press
    longPressGesture.delegate = self
    self.tableView.addGestureRecognizer(longPressGesture)

}

Ve fonksiyon:

func handleLongPress(longPressGesture:UILongPressGestureRecognizer) {

    let p = longPressGesture.locationInView(self.tableView)
    let indexPath = self.tableView.indexPathForRowAtPoint(p)

    if indexPath == nil {
        print("Long press on table view, not row.")
    }
    else if (longPressGesture.state == UIGestureRecognizerState.Began) {
        print("Long press on row, at \(indexPath!.row)")
    }

}

6

Anna Karenina'nın mükemmel cevabına dayanarak UITableView'da küçük bir kategori oluşturdum.

Bunun gibi, normal tablo görünümleriyle uğraşırken alıştığınız gibi uygun bir temsilci yöntemine sahip olacaksınız. Bunu kontrol et:

//  UITableView+LongPress.h

#import <UIKit/UIKit.h>

@protocol UITableViewDelegateLongPress;

@interface UITableView (LongPress) <UIGestureRecognizerDelegate>
@property(nonatomic,assign)   id <UITableViewDelegateLongPress>   delegate;
- (void)addLongPressRecognizer;
@end


@protocol UITableViewDelegateLongPress <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didRecognizeLongPressOnRowAtIndexPath:(NSIndexPath *)indexPath;
@end



//  UITableView+LongPress.m

#import "UITableView+LongPress.h"

@implementation UITableView (LongPress)
@dynamic delegate;

- (void)addLongPressRecognizer {
    UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
                                          initWithTarget:self action:@selector(handleLongPress:)];
    lpgr.minimumPressDuration = 1.2; //seconds
    lpgr.delegate = self;
    [self addGestureRecognizer:lpgr];
}


- (void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
    CGPoint p = [gestureRecognizer locationInView:self];

    NSIndexPath *indexPath = [self indexPathForRowAtPoint:p];
    if (indexPath == nil) {
        NSLog(@"long press on table view but not on a row");
    }
    else {
        if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
            // I am not sure why I need to cast here. But it seems to be alright.
            [(id<UITableViewDelegateLongPress>)self.delegate tableView:self didRecognizeLongPressOnRowAtIndexPath:indexPath];
        }
    }
}

Bunu bir UITableViewController içinde kullanmak istiyorsanız, muhtemelen alt sınıfa ayırmanız ve yeni protokole uymanız gerekir.

Benim için harika çalışıyor, umarım başkalarına yardımcı olur!


Heyet ve kategori modellerinin inanılmaz kullanımı
valeCocoa

5

Swift 3 cevap, modern sözdizimini kullanarak, diğer cevapları dahil ederek ve gereksiz kodu ortadan kaldırır.

override func viewDidLoad() {
    super.viewDidLoad()
    let recognizer = UILongPressGestureRecognizer(target: self, action: #selector(tablePressed))
    tableView.addGestureRecognizer(recognizer)
 }

@IBAction func tablePressed(_ recognizer: UILongPressGestureRecognizer) {
    let point = recognizer.location(in: tableView)

    guard recognizer.state == .began,
          let indexPath = tableView.indexPathForRow(at: point),
          let cell = tableView.cellForRow(at: indexPath),
          cell.isHighlighted
    else {
        return
    }

    // TODO
}

2

Film şeridinde verilen prototip hücresine UILongPressGestureRecognizer'ı ekleyin, ardından bir eylem yöntemi oluşturmak için hareketi viewController'ın .m dosyasına çekin. Dediğim gibi yaptım.


Biraz daha açıklayabilir misiniz? Prototip hücresini VC'nizde bir özellik haline getirdiniz mi?
Ethan Parker

-2

UITouch zaman damgası özelliğini dokunuşlarda kullanınBir zamanlayıcı başlatmak için dokunun veya dokunulduğunda durdurun


Cevabınız için teşekkürler, ancak hangi satırın dokunmayla ilgili olduğunu nasıl belirleyebilirim?
foOg

Yanılıyor olabilirim, ama bunu yapmanıza yardımcı olacak hiçbir şey yoktur. [TableView indexPathsForVisibleRows] ile geçerli görünür hücrelerin dizinlerini almanız ve ardından bazı hesaplamalar (tableView üstünüzden üste + X kat fazla satır) ile parmağınızın koordinatlarının hangi konumda olduğunu bileceksiniz. kürek çekmek.
Thomas Joulin

Eminim bunu yapmanın daha kolay bir yolu var, yine de başka bir fikriniz varsa, burada olacağım :)
foOg

Daha kolay bir şey olup olmadığını da bilmek beni mutlu eder. Ama orada olduğunu sanmıyorum, çünkü Apple'ın etkileşimlerle başa çıkmamızı istediği yol bu değil ... Bu "hızlı erişim menüsünü" düşünmenin bir Android yolu gibi görünüyor. Benim uygulamam olsaydı, Twitter uygulaması gibi hallederim. Sola
kaydırdığınızda

Evet, bunu düşündüm, bu yüzden gerçekten uzun bir basın etkinliği ile yapamazsam, kaydırma yöntemini kullanacağım. Ama, yığın-taşma belki birileri ... did it
foOg
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.