#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:
Я сталкивался с проблемой долгое время и не получил никакого рабочего решения. Наконец, я выбираю альтернативу. Я знаю, что технически это не решение, но это может помочь кому-то, кто наверняка ищет то же самое.
В моем случае я хочу выбрать строку, в которой будет отображаться какой-либо параметр, после этого я касаюсь любого места в таблице или представлении, я хочу скрыть эти параметры или выполнить любую задачу, кроме строки, выбранной ранее, для этого я сделал следующее:
-
Установите события касания для просмотра. Это выполнит задачу, когда вы коснетесь любого места в представлении, кроме табличного представления.
-
В 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 к методу, объявленному выше. Надеюсь, это поможет.