События касания в UITableView?

#iphone #uitableview #uiviewcontroller #touches

#iPhone #uitableview #uiviewcontroller #касания

Вопрос:

У меня есть UIViewController и UITableView в качестве дочернего элемента в представлении, что я хочу сделать, так это когда я касаюсь любой строки, я показываю представление внизу. Я хочу скрыть это представление, если пользователь коснется любого другого места, а затем строк или bottomView.

Проблема в том, что когда я нажимаю на, UITableView это не запускает touchesEnded событие.

Теперь, как я могу обнаружить касание UITableView и отличить его с помощью события выбора строки.

Спасибо.

Комментарии:

1. Я не уверен, что понимаю. Вы имеете в виду, что у вас есть UIView (ViewA), который содержит UITableView, и другой UIView (ViewB) (внизу). Если пользователь касается чего-либо другого, кроме UITableViewCell или ViewB, то вы хотите скрыть ViewB. В противном случае отобразится ViewB. это правильно?

2. Да, именно это я хочу сделать .. И если пользователь коснется UITableViewCell, я хочу показать ViewB. Этого я могу достичь с помощью didRowSelectedAtIndexPath:

3. Итак, вы спрашиваете.. «как вы фиксируете события касания, которые происходят в UITableView, но не в ячейке?»

4. Да, конечно.. Мне нужно определить касание UITableView, а не ячейки

Ответ №1:

Не нужно ничего подклассировать, вы можете добавить UITapGestureRecognizer к UITableView и использовать жест или нет, в зависимости от ваших критериев.

В вашем viewDidLoad:

 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapOnTableView:)];
[self.myTableView addGestureRecognizer:tap];
  

Затем выполните свое действие следующим образом для критериев:

 -(void) didTapOnTableView:(UIGestureRecognizer*) recognizer {
    CGPoint tapLocation = [recognizer locationInView:self.myTableView];
    NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:tapLocation];

    if (indexPath) { //we are in a tableview cell, let the gesture be handled by the view
        recognizer.cancelsTouchesInView = NO;
    } else { // anywhere else, do what is needed for your case
        [self.navigationController popViewControllerAnimated:YES];
    }
}
  

И обратите внимание, что если вы просто хотите получать щелчки в любом месте таблицы, но не по каким-либо кнопкам в строках ячеек, вам нужно использовать только первый фрагмент кода выше. Типичный пример — когда у вас есть UITableView, а также панель пользовательского поиска. Вы хотите исключить панель поиска, когда пользователь нажимает, прокручивает и т.д. табличное представление. Пример кода…

 -(void)viewDidLoad {
    [super viewDidLoad];
    etc ...

    [self _prepareTable];
}
-(void)_prepareTable {
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    self.tableView.allowsSelection = NO;
    etc...

    UITapGestureRecognizer *anyTouch =
        [[UITapGestureRecognizer alloc]
         initWithTarget:self action:@selector(tableTap)];
    [self.tableView addGestureRecognizer:anyTouch];
}
// Always drop the keyboard when the user taps on the table:
// This will correctly NOT affect any buttons in cell rows:
-(void)tableTap {
    [self.searchBar resignFirstResponder];
}
// You probably also want to drop the keyboard when the user is
// scrolling around looking at the table. If so:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
    [self.searchBar resignFirstResponder];
}
// Finally you may or may not want to drop the keyboard when
// a button in one cell row is clicked. If so:
-(void)clickedSomeCellButton... {
    [self.searchBar resignFirstResponder];
    ...
}
  

Надеюсь, это кому-то поможет.

Комментарии:

1. Я предпочитаю вызывать resignFirstResponder внутри метода scrollViewWillBeginDragging:(UIScrollView *)ScrollView вместо scrollViewDidScroll. Потому что, если пользователь будет прокручивать, а затем нажимать на панель поиска во время замедления прокрутки — клавиатура появится на экране на секунду, а затем она скроется, что не является подходящим поведением. С помощью метода scrollViewWillBeginDragging эта проблема решена.

Ответ №2:

Вы должны переслать событие касания на контроллер представления. Создайте подкласс вашего элемента управления tableview, а затем переопределите метод:

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];  //let the tableview handle cell selection 
    [self.nextResponder touchesBegan:touches withEvent:event]; // give the controller a chance for handling touch events 
}
  

затем вы можете делать то, что хотите, с помощью сенсорных методов контроллера.

Комментарии:

1. Спасибо @ longway, но я не получаю вызов touchsBegan, чем как я могу перенаправить его на контроллер view??? Весь вопрос в том, как вызвать событие touchesBegan, когда я касаюсь TableView 🙂

2. вы создаете подкласс UITableView, переопределяете методы обработки касания. Затем вы создаете свою таблицу, используя свой пользовательский класс tableview

3. Привет, я попробовал ваше решение, которое, конечно, работает для обнаружения topuch в tableview и перехода к соответствующему супервизору. Теперь у меня проблема с тем, что метод делегирования UITableView, то есть didSelectRowAtIndexPath, не вызывается. В конечном счете, чего я хочу, так это сначала обнаружить касание в tableview, передать его супервизору, выполнить некоторое действие, а затем выполнить didSelectRowAtIndexPath. Можете ли вы помочь мне в этом??

Ответ №3:

Я только что наткнулся на то, что может быть решением вашей проблемы. Используйте этот код при создании табличного представления:

 tableView.canCancelContentTouches = NO;
  

Без установки этого значения NO события касания отменяются, как только в вашем табличном представлении происходит хотя бы небольшое вертикальное перемещение (если вы добавите в свой код инструкции NSLog, вы увидите, что touchesCancelled это вызывается, как только таблица начинает прокручиваться по вертикали).

Комментарии:

1. ваше решение не работает. Я попробовал ваше решение и использовал все события касания, включая журнал touchesCancelled . В viewDidLoad я установил [tblTemp setCanCancelContentTouches:NO]; . Вызывается не мой сенсорный метод.

Ответ №4:

Я сталкивался с проблемой долгое время и не получил никакого рабочего решения. Наконец, я выбираю альтернативу. Я знаю, что технически это не решение, но это может помочь кому-то, кто наверняка ищет то же самое.

В моем случае я хочу выбрать строку, в которой будет отображаться какой-либо параметр, после этого я касаюсь любого места в таблице или представлении, я хочу скрыть эти параметры или выполнить любую задачу, кроме строки, выбранной ранее, для этого я сделал следующее:

  1. Установите события касания для просмотра. Это выполнит задачу, когда вы коснетесь любого места в представлении, кроме табличного представления.

  2. В TableView didSelectRowAtIndexPath было выполнено следующее

      - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
        if(indexPath.row != previousSelectedRow amp;amp; previousSelectedRow != -1) {
            // hide options or whatever you want to do
            previousSelectedRow = -1;
        }
        else {
            // show your options or other things
            previousSelectedRow = indexPath.row;
        }
     }
      

Я знаю, что это более старый пост и не очень хорошее техническое решение, но у меня это сработало. Я публикую этот ответ, потому что это может кому-то наверняка помочь.

Примечание: В написанном здесь коде могут быть орфографические ошибки, поскольку он был введен непосредственно здесь . 🙂

Ответ №5:

Попробуйте эти методы:

 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{

}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{

}
  

Используйте scrollViewDidEndDragging как альтернативу touchesEnded. Надеюсь, это поможет.

Ответ №6:

Для получения событий касания на UITableView используйте:

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
  //<my stuff>

  [super touchesBegan:touches withEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
   //<my stuff>

   [super touchesMoved:touches withEvent:event];
}

- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
  //<my stuff>

  [super touchesEnded:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
   //<my stuff>
   [super touchesCancelled:touches withEvent:event];
}
  

Ответ №7:

В вашем классе контроллера объявите метод, который удаляет вид снизу. Что-то вроде этого:

 -(IBAction)bottomViewRemove:(id)sender {

[bottomView removeFromSuperview];

}
  

В Interface Builder выберите свой вид, а в инспекторе идентификации в разделе пользовательский класс измените класс с UIView на UIControl . После этого перейдите в инспектор подключений и подключите событие touchUpInside к методу, объявленному выше. Надеюсь, это поможет.