UITableView पर लंबी प्रेस


191

मैं एक लंबे प्रेस को संभालना चाहूंगा UITableViewCell "त्वरित पहुंच मेनू" प्रिंट । क्या किसी ने पहले से ही ऐसा किया?

विशेष रूप से इशारे पर पहचान UITableView?

जवाबों:


427

सबसे पहले टेबल व्यू में लॉन्ग प्रेस जेस्चर पहचानकर्ता जोड़ें:

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

फिर इशारे में हैंडलर:

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

आपको इसके साथ सावधान रहना होगा ताकि यह उपयोगकर्ता के सेल के सामान्य दोहन में हस्तक्षेप न करे और यह भी ध्यान दें कि handleLongPressकई बार आग लग सकती है (यह जेस्चर पहचानकर्ता राज्य परिवर्तनों के कारण होगा)।


1
बहुत बढ़िया !!! आपका बहुत बहुत धन्यवाद! लेकिन एक आखिरी छोटा सा सवाल: जब टच खत्म हो गया है तो मेथड हैंडल क्यों है?
फोक्सग

111
सुधार: यह इशारा के विभिन्न राज्यों को इंगित करने के लिए कई बार आग लगाता है (शुरू, परिवर्तित, समाप्त, आदि)। तो हैंडलर विधि में, इशारे के प्रत्येक राज्य पर कार्रवाई करने से बचने के लिए जेस्चर पहचानकर्ता की राज्य संपत्ति की जांच करें। उदाहरण के लिए: if (gestureRecognizer.state == UIGestureRecognizerStateBegan) ...

3
मत भूलो, जेस्चर पहचानकर्ता को अब यूआई तत्वों में सीधे इंटरफ़ेस बिल्डर में जोड़ा जा सकता है और एक IBAction विधि के माध्यम से जोड़ा जा सकता है, इसलिए यह उत्तर और भी आसान है ;-) (केवल पहचानकर्ता को संलग्न करना याद रखें UITableView, नहीं UITableViewCell...)

10
इसके अलावा UIGestureRecognizerDelegate प्रोटोकॉल की पुष्टि class.h फ़ाइल में करें
Vaquita

1
आप सेल में नेविगेट करने से टेबल व्यू को कैसे रोक सकते हैं (यदि आपके पास 'doSelectRowAtIndexPath' लागू है)?
Marchy

46

मैंने अन्ना-कारेनिना के उत्तर का उपयोग किया है, और यह एक बहुत ही गंभीर बग के साथ लगभग महान काम करता है।

यदि आप अनुभागों का उपयोग कर रहे हैं, तो अनुभाग शीर्षक को लंबे समय तक दबाने से आपको उस खंड पर पहली पंक्ति दबाने का गलत परिणाम मिलेगा, मैंने नीचे एक निश्चित संस्करण जोड़ दिया है (इशारे की स्थिति के आधार पर डमी कॉल को फ़िल्टर करने सहित) अन्ना-करिनेना सुझाव)।

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

हाय @ ममोरर: मैं पूछना चाहता हूं कि क्या यह संभव है कि केवल एक दृश्य जिसे उपयोगकर्ता ने छुआ है, के एक हिस्से की पहचान कर सके?
मंथन

अरे, आप उसके लिए हिटटेस्ट ( डेवलपर . apple.com/library/ios/documentation/uikit/reference/… ) का उपयोग कर सकते हैं । उदाहरण का उपयोग करने के तरीके के लिए इस उत्तर की जाँच करें: stackoverflow.com/a/2793253/819355
मार्मोर '10

जबकि स्वीकृत उत्तर काम करता है। यह स्क्रीन पर खींचते समय लॉगिंग के साथ-साथ कई फायर करता है। यह उत्तर नहीं है। एक कानूनी प्रति और पेस्ट उत्तर। धन्यवाद।
क्रिसओएसएक्स

29

स्विफ्ट 5 में उत्तर (स्विफ्ट में रिकी के जवाब की निरंतरता)

UIGestureRecognizerDelegateअपने ViewController में जोड़ें

 override func viewDidLoad() {
    super.viewDidLoad()

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

और समारोह:

@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

यहाँ डॉन सॉन्ग के उत्तर और मर्मर के उत्तर को मिलाकर स्पष्ट निर्देश दिए गए हैं।

एक लंबी प्रेस Gesture Recognizer खींचें और इसे अपनी Table सेल में छोड़ें। यह बाईं ओर सूची के नीचे कूद जाएगा।

यहां छवि विवरण दर्ज करें

फिर जेस्चर पहचानकर्ता को उसी तरह कनेक्ट करें जिस तरह से आप एक बटन कनेक्ट करेंगे। यहां छवि विवरण दर्ज करें

एक्शन हैंडलर में मर्मर से कोड जोड़ें

- (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
मेरी राय में सबसे अच्छा जवाब
एसेन कासिमोव

8
लॉन्ग प्रेस जेस्चर रिकॉगनाइज़र को टेबल व्यू नॉट सेल व्यू सेल पर लागू किया जाना चाहिए। इसे टेबल व्यू सेल में छोड़ने पर केवल पंक्ति 0 होगी जो लंबी प्रेस को सुन रही है।
एलेक्स

14

यहां सेल में सीधे पहचानकर्ता को जोड़ने के लिए अधिक कुशल लगता है:

TableView सेल के लिए टैप और होल्ड करें, तब और अब

(नीचे के उदाहरण पर स्क्रॉल करें)


7
प्रत्येक तालिका के लिए एक नया जेस्चर पहचानकर्ता ऑब्जेक्ट कैसे आवंटित किया जा सकता है जो पूरी तालिका के लिए एक एकल पहचानकर्ता से अधिक कुशल है?
user2393462435

7
याद रखें कि यदि केवल कुछ कोशिकाएं बनी हुई हैं, तो सही तरीके से काम नहीं कर रहा है।
चींटियों

11

उत्तर स्विफ्ट में:

UIGestureRecognizerDelegateअपने UITableViewController में प्रतिनिधि जोड़ें ।

UITableViewController के भीतर:

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)

}

और समारोह:

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

मैंने अन्ना कारेनिना के उत्कृष्ट उत्तर के आधार पर UITableView पर एक छोटी सी श्रेणी को एक साथ रखा।

इस तरह आपके पास एक सुविधाजनक प्रतिनिधि तरीका होगा जैसे आप नियमित टेबल व्यू से निपटने के लिए उपयोग किए जाते हैं। इसकी जांच - पड़ताल करें:

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

यदि आप UITableViewController में इसका उपयोग करना चाहते हैं, तो आपको संभवतः नए प्रोटोकॉल को उप-वर्ग और उसके अनुरूप करने की आवश्यकता है।

यह मेरे लिए बहुत अच्छा काम करता है, आशा है कि यह दूसरों की मदद करेगा!


प्रतिनिधिमंडल और श्रेणी पैटर्न का अद्भुत उपयोग
valeCocoa

5

आधुनिक सिंटैक्स का उपयोग करते हुए, अन्य उत्तरों को शामिल करने और अनावश्यक कोड को समाप्त करने के लिए 3 उत्तर को स्विफ्ट करें।

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

स्टोरीबोर्ड में दिए गए प्रोटोटाइप सेल में बस UILongPressGestureRecognizer जोड़ें, फिर एक कार्य विधि बनाने के लिए viewController .m फ़ाइल के लिए इशारा खींचें। मैंने जैसा कहा था, वैसा ही बना दिया।


क्या आप थोड़ा और समझा सकते हैं? क्या आपने प्रोटोटाइप सेल को अपने वीसी में संपत्ति बनाया था?
एथन पार्कर

-2

टचबॉक्स में UITouch टाइमस्टैम्प संपत्ति का उपयोग करें टाइमर को लॉन्च करने के लिए या टच करने पर रोकें


आपके उत्तर के लिए धन्यवाद, लेकिन मैं कैसे पता लगा सकता हूं कि कौन सी पंक्ति स्पर्श से संबंधित है?
13:05

मैं गलत हो सकता हूं, लेकिन आपको ऐसा करने में मदद करने के लिए कुछ भी प्रदान नहीं किया जाता है। आपको वर्तमान दृश्यमान कोशिकाओं की अनुक्रमणिका को [tableView indexPathsForVanishRows] के साथ प्राप्त करना होगा और फिर, कुछ गणनाओं का उपयोग करके (आपका tableView पंक्तियों के शीर्ष + X बार से ऑफसेट होगा) आपको पता चल जाएगा कि आपकी उंगली के निर्देशांक किस पर हैं पंक्ति।
बजे थॉमस जूलिन

मुझे यकीन है कि ऐसा करने का एक आसान तरीका है, वैसे भी अगर आपके पास एक और विचार है, तो मैं यहां
आऊंगा

मुझे यह जानकर खुशी होगी कि अगर कुछ आसान संभव है। लेकिन मुझे नहीं लगता है कि ज्यादातर ऐसा इसलिए है क्योंकि ऐप्पल नहीं चाहता है कि हम बातचीत को संभालें ... यह "त्वरित पहुँच मेनू" सोचने का एक एंड्रॉइड तरीका है। अगर यह मेरा ऐप था, तो मैं इसे ट्विटर ऐप की तरह संभालूंगा। बाईं ओर एक स्वाइप विकल्प प्रदर्शित करता है
थॉमस जूलिन

हां, मैंने इसके बारे में सोचा, इसलिए अगर मैं वास्तव में एक लंबी प्रेस घटना के साथ ऐसा नहीं कर सकता, तो मैं स्वाइप विधि का उपयोग करूंगा। लेकिन, हो सकता है ढेर-अतिप्रवाह में किसी को यह किया ...
foOg
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.