Я хочу обработать длинное нажатие на UITableViewCell
, чтобы напечатать «меню быстрого доступа». Кто-то уже сделал это?Длинное нажатие на UITableView
В частности, распознать жест на UITableView
?
Я хочу обработать длинное нажатие на UITableViewCell
, чтобы напечатать «меню быстрого доступа». Кто-то уже сделал это?Длинное нажатие на UITableView
В частности, распознать жест на 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);
}
}
Вы должны быть осторожны с этим, так что это не мешает нормальному постукивания пользователя ячейки, а также отметить, т hat handleLongPress
может срабатывать несколько раз (это будет связано с изменением состояния распознавателя жестов).
Используйте метку времени свойство UITouch в touchesBegan, чтобы запустить таймер или остановить его, когда touchesEnded был уволен
Спасибо за ваш ответ, но как я могу определить, какая строка касается касания? – foOg
Возможно, я ошибаюсь, но ничего не предоставляется, чтобы помочь вам в этом. Вам нужно будет получить индексы текущих видимых ячеек с помощью [tableView indexPathsForVisibleRows], а затем, используя некоторые вычисления (смещение tableView сверху + X раз строк), вы будете знать, что координаты вашего пальца находятся на ряд. –
Я уверен, что есть более простой способ сделать это, так или иначе, если у вас есть другая идея, я буду здесь :) – foOg
кажется более эффективным, чтобы добавить распознаватель непосредственно в камеру, как показано здесь:
Tap&Hold for TableView Cells, Then and Now
(прокрутка к примеру в нижней части)
Как можно назначить новый объект распознавания жестов для каждой строки более эффективным, чем один распознаватель для всей таблицы? – user2393462435
Помните, что существует только несколько ячеек, если dequeue работает правильно. – Ants
Я использовал Anna-Карениной ответ, и он работает почти отлично с очень серьезной ошибкой.
Если вы используете разделы, длительное нажатие на заголовок раздела приведет к неправильному результату нажатия первой строки в этом разделе, я добавил исправленную версию ниже (включая фильтрацию фиктивных вызовов на основе состояние жестов, по предложению Анны-Каренины).
- (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);
}
}
}
}
Привет @marmor: Я хочу спросить, можно ли идентифицировать только часть вида, к которому пользователь прикасался? – Manthan
Эй, вы можете использовать hitTest для этого (https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html#//apple_ref/occ/instm/UIView/hitTest: withEvent :). Проверьте этот ответ, например, о том, как использовать: http://stackoverflow.com/a/2793253/819355 – marmor
Хотя принятый ответ работает. Он регистрирует многократные пожары, а также ведет журнал при перетаскивании по экрану. Этот ответ не делает. Ответ на законную копию и вставку. Спасибо. – ChrisOSX
Я собрал небольшую категорию в 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, вы, вероятно, необходимо создать подкласс и соответствовать новому протоколу.
Это отлично работает для меня, надеюсь, что это поможет другим!
Просто добавьте UILongPressGestureRecognizer к данной ячейке прототипа в раскадровке, затем потяните жест в файл .m-файла viewController, чтобы создать метод действия. Я сделал это, как я уже сказал.
Можете ли вы объяснить немного больше? Вы сделали прототип ячейки собственностью в вашем VC? –
Здесь поясняются инструкции, сочетающие ответ Песни Рассвета и ответ Мармора.
Перетащите длинный указатель распознавания жестов и поместите его в свою ячейку. Он переместится в нижнюю часть списка слева.
Затем подключите этот жест распознаватель так же, как вы бы подключить кнопку.
Добавьте код из Мармора в обработчик действия
- (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);
}
}
}
}
Лучший ответ на мой взгляд –
Длинный указатель жестов печати следует применять к ячейке просмотра таблицы не таблицы. Отбрасывание его в ячейку таблицы будет иметь только прослушивание строки 0 при длительном нажатии. – Alex
Ответ в Swift:
Добавить делегат 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)")
}
}
Ответ в Swift 3.0 (Continuatuin ответа Рики в Swift)
Добавьте
UIGestureRecognizerDelegate
вашему ViewController
override func viewDidLoad() {
super.viewDidLoad()
//Long Press
let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
longPressGesture.minimumPressDuration = 0.5
longPressGesture.delegate = self
self.tableView.addGestureRecognizer(longPressGesture)
}
И функция:
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 == UIGestureRecognizerState.began) {
print("Long press on row, at \(indexPath!.row)")
}
}
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
}
Awesome !!! Большое спасибо! Но последний маленький вопрос: почему метод handleLongPress вызывается, когда контакт закончился? – foOg
Он не вызывается при касании, но может срабатывать несколько раз, если пользователь держит палец на ячейке более 4 секунд (в этом примере), прежде чем поднимать его. – Anna
Коррекция: он срабатывает несколько раз, чтобы указать различные состояния жестов (началось, изменено, закончено и т. Д.). Поэтому в методе обработчика проверьте свойство состояния распознавателя жестов, чтобы избежать действия в каждом состоянии жестов. Например: 'if (gestureRecognizer.state == UIGestureRecognizerStateBegan) ...'. – Anna