سؤال

أود التعامل مع الضغط الطويل على UITableViewCell لطباعة "قائمة وصول سريعة". هل قام شخص ما بالفعل بذلك؟

لا سيما إيماءة تعترف بها UITableView?

هل كانت مفيدة؟

المحلول

قم أولاً بإضافة معرف الإيماءات الطويل إلى عرض الجدول:

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 قد يطلق النار عدة مرات (سيكون هذا بسبب تغييرات حالة التعرف على الإيماءات).

نصائح أخرى

لقد استخدمت إجابة Anna-Karenina ، وهي تعمل بشكل رائع تقريبًا مع خطأ خطير للغاية.

إذا كنت تستخدم أقسامًا ، فسوف يمنحك عنوان القسم نتيجة خاطئة للضغط على الصف الأول في هذا القسم ، لقد أضفت نسخة ثابتة أدناه (بما في ذلك تصفية المكالمات الوهمية بناءً على حالة الإيماءة ، لكل اقتراح آنا كارنينا).

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

فيما يلي تعليمات موضحة تجمع بين إجابة Dawn Song وإجابة Marmor.

اسحب معرفات الإيماءات الطويلة اضغط وإسقاطها في خلية الطاولة الخاصة بك. سوف تقفز إلى أسفل القائمة على اليسار.

enter image description here

ثم قم بتوصيل معرف التعرف على الإيماءات بنفس الطريقة التي تقوم بتوصيلها بزر.enter image description here

أضف الكود من Marmor في معالج الإجراء

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

}

إجابة في Swift 5 (استمرار إجابة ريكي في سويفت)

أضف ال UIGestureRecognizerDelegate إلى ViewController الخاص بك

 override func viewDidLoad() {
    super.viewDidLoad()

    //Long Press
    let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
    longPressGesture.minimumPressDuration = 0.5
    longPressGesture.delegate = self
    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)")
    }
}

يبدو أنه أكثر كفاءة لإضافة معرف التعرف مباشرة إلى الخلية كما هو موضح هنا:

اضغط مع الاستمرار على خلايا TableView ، ثم والآن

(قم بالتمرير إلى المثال في الأسفل)

الجواب في سويفت:

إضافة مندوب 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)")
    }

}

قمت بتجميع فئة صغيرة على UitableView استنادًا إلى إجابة Anna Karenina الممتازة.

مثل هذا سيكون لديك طريقة مندوب مريحة كما كنت معتادا عند التعامل مع طرق عرض الجدول العادية. تحقق من ذلك:

//  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 ، فربما تحتاج إلى فئة فرعية وتتوافق مع البروتوكول الجديد.

إنه يعمل بشكل رائع بالنسبة لي ، آمل أن يساعد الآخرين!

إجابة Swift 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
}

ما عليك سوى إضافة UilongPressUserEcognizer إلى خلية النموذج الأولي المعطى في القصة المصورة ، ثم اسحب الإيماءة إلى ملف .M's ViewController لإنشاء طريقة عمل. لقد صنعتها كما قلت.

استخدم خاصية UITouch Timestamp في Touchesbegan لإطلاق مؤقت أو إيقافه عند إطلاق اللمسات

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top