Нажатие на UITextField в UITableViewCell
У меня проблема, когда при нажатии textField
в UITableViewCell
метод tableView:didSelectRowAtIndexPath:
не запускается. Проблема в том, что мне нужно прокрутить мой tableView
в правильное положение, иначе клавиатура будет идти прямо над первым ответчиком.
Затем я должен переместить код следующим образом:
[[self tableView] scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
как в моем методе делегата tableView
, так и в методе делегата UITextField
, textFieldDidBeginEditing:
.
Является лучшим способом просто создать новый метод, передать ему индексную ячейку ячейки/текстового поля и вызвать метод как из делегата tableView, так и из делегата UITextField
? лучший способ обойти это?
Ответы
Ответ 1
Я нашел следующие работы хорошо (предполагается, что вы находитесь в контроллере табличного представления)
- (void)textFieldDidBeginEditing:(UITextField *)textField{
CGPoint pnt = [self.tableView convertPoint:textField.bounds.origin fromView:textField];
NSIndexPath* path = [self.tableView indexPathForRowAtPoint:pnt];
[self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
Ответ 2
Есть несколько способов решить эту проблему. Что происходит, так это то, что tableViewCell делегирует событие касания к его подзонам, что заставляет текстовое поле обрабатывать касание вместо вашей ячейки.
Чтобы исправить это:
-
Задайте для свойства userinteractionEnabled для UITextfield значение НЕТ, а затем, когда вы получите сообщение didSelectRowAtIndexPath, вы снова включите userInteractionEnabled и вызовите TextField, чтобы получить FirstResponder. На v2.2 вам даже не нужно устанавливать флаг userInteractionEnabled, я не тестировал его с другими версиями, однако в документации достаточно ясно, что вы должны включить это. в tableViewController вам просто нужно сохранить индексный путь до тех пор, пока вы не получите сообщение UIKeyboardDidShow
-
Создайте делегат для UITextField, который отправляется обратно в ваш tableViewController, чтобы вы могли установить смещение прокрутки.
-
зарегистрируйтесь для событий клавиатуры, а затем выясните прокрутку, проверив, какое текстовое поле находится в режиме редактирования.
Ответ 3
Вы можете установить ваш контроллер в качестве делегата вашего UITextField, а затем настроить представление таблицы в textFieldDidBeginEditing:
или textFieldShouldBeginEditing:
Ответ 4
Я не нашел решений, которые работают для меня в Интернете. После нескольких дней работы в Google и экспериментов я, наконец, получил это хорошо. Это сложная ошибка в Apple iPhone, как вы увидите в конце этого сообщения.
Если вы столкнулись с проблемой, подобной мне, следующим образом:
-
у которого tableviewcell больше половины экрана iphone (не путайте с примерами Apple UICatalog, у них есть короткая ячейка tableview менее 50 пунктов, здесь не применимо.),
-
имеющий более одного поля uitex в ячейке или комбинацию uitextfield и uitextview или uiwebview в ячейке,
-
Нажатие между uitextfields и uitextview или uiwebview приводит к непредсказуемой позиции прокрутки, либо щелкнуло uitextfield, которое выпрыгивает из поля зрения или покрывается keybaord. Он работает только в первый раз, когда клавиатура появляется в tableviewcell и не работает в дальнейшем.
У меня был большой прорыв после чтения сообщений, похожих на этот: http://alanduncan.net/old/index.php?q=node/13 Они тоже не поняли. Боль вызвана ошибкой в событиях UIKeyboard. Когда клавиатура сначала появляется, она выдает UIKeyboardWillShowNotification и UIKeybaordDidShowNotification. Theree - ошибка в iPhone, так как первая UIKeyboardWillShowNotification отличается от последующей UIKeyboardWillShowNotification. Решение - НАБЛЮДАТЬ UIKeyboardDidShowNotification. Поэтому, когда ваша ячейка появится, добавьте следующий код
NSNotificationCenter*nc=[NSNotificationCenter defaultCenter];
[nc addObserver:self selectorselector(keyboardDidShow name:UIKeyboardDidShowNotification object:self.window];
В функции keyboardDidShow нам нужно прокрутить TABLEVIEW, а не tableviewcell, как указано выше. Или вы можете видеть, что различные объекты идут раздельно, а не прокручиваются вместе в одном куске.
(void)keyboardDidShow:(NSNotification *)notif
{
//1. see which field is calling the keyboard
CGRect frame;
if([textField_no1 isFirstResponder])
frame=textField_no1.frame;
else if([textField_no2 isFirstResponder])
frame=textField_no2.frame;
else if([textField_no3 isFirstResponder])
frame=textField_no3.frame;
else if([textView isFirstResponder])
frame=textView.frame;
else return;
CGRect rect=self.superview.frame;
//2. figure out how many pixles to scroll up or down to the posistion set by theKeyBoardShowUpHorizon.
//remove the complexity when the tableview has an offset
[((UITableView*)[self.superview).setContentOffset:CGPointMake(0,0) animated:YES];
int pixelsToMove=rect.origin.y+ frame.origin.y-theKeyBoardShowUpHorizon;
//3. move the uitableview, not uitableviewcell
[self moveViewUpOrDownByPixels:pixelsToMove];
}
- (void)moveViewUpOrDownByPixels:(int)pixels
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.6];
//find the position of the UITableView, the superView of this tableview cell.
CGRect rect=self.superview.frame;
//moves tableview up (when pixels >0) or down (when pixels <0)
rect.origin.y -= pixels;
rect.size.height += pixels;
self.superview.frame = rect;
[UIView commitAnimations];
}
Чтобы восстановить таблицуView назад, вам нужно добавить наблюдателя в UIKeyboardDidHideNotification (а не UIKeyboardWillHideNotification, как было предложено другими сообщениями, чтобы избежать мерцания), где вы каждый раз видите tableviewcell и возвращаете табличное представление туда, где оно было.
[nc addObserver:self selectorselector(keyboarDidHide) name:UIKeyboardDidHideNotification object:nil];
- (void)keyboardDidHideNSNotification*)notif
{
//we have moved the tableview by number of pixels reflected in (self.superview.frame.origin.y). We need to move it back
[self moveViewUpOrDownByPixels:self.superview.frame.origin.y];
}
Не забывайте удалять оба наблюдателя, когда ваша ячейка исчезает с помощью [[NSNotificationCenter defaultCenter] removeObserver:...
Это все, что нужно. Надеюсь, Apple iPhone команда в один прекрасный день решит эту проблему, может быть, в 4.0 через несколько месяцев.
Ответ 5
Я нашел решение.
- Откройте файл .xib в построителе интерфейсов.
- Выберите представление таблицы
- Из меню IB выберите Tools- > Size Inspector
В разделе "Размер прокрутки" измените Вставить → Нижнее значение на 100, 150, 250 в зависимости от того, насколько велик ваш табличный вид.
код
-(void) textFieldDidBeginEditing:(UITextField *)textField
{
UITableViewCell *cell = (UITableViewCell *) [[textField superview] superview];
[self.tableView scrollToRowAtIndexPath:[tableView indexPathForCell:cell]
atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
Ответ 6
Я обнаружил, что на самом деле это довольно легко сделать.
Метод делегата UITextField textFieldDidBeginEditing предоставит вам текстовое поле, которое затем можно сопоставить с indexPath, используя:
self.currentIndexPath = [self.tableView indexPathForRowAtPoint:textField.frame.origin];
Затем вы можете прокрутить ячейку в виде (т.е. в вашем обработчике уведомлений клавиатуры UIKeyboardDidShowNotification):
[self.tableView scrollToRowAtIndexPath:self.currentIndexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
Ответ 7
didSelectRowAtIndexPath не будет вызываться для встроенных ячеек UITextField; следовательно, логика прокрутки должна быть в другом месте.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1];
UITableViewCell *cell = [_tableView cellForRowAtIndexPath:indexPath];
[_tableView setContentOffset:CGPointMake(0, cell.frame.size.height) animated:YES];
}
Удостоверьтесь, что текстовый делегат textField включен
Ответ 8
Зарегистрируйтесь для UIKeyboardWillShowNotification и UIKeyboardWillHideNotification, а затем настройте свое представление по необходимости в обработчиках уведомлений. Один из примеров приложений показывает, как это сделать, но я забыл, какие... SQLiteBooks, или, возможно, EditableDetailView.
Ответ 9
Я боролся с этой же проблемой, где у меня UITextFields внутри UITableViewCells и не смог получить представление для прокрутки к полю при его редактировании. Ядро моего решения ниже.
Ключ к этому коду - это строка, в которой создается UITextField. Вместо жесткого кодирования значения x и y в функции CGRectMake() он использует x и y из ячейки, в которой он помещается (+/- любое смещение, которое вы хотите от краев ячейки, как показано ниже). Значения жесткого кодирования x и y в UITextField * дают каждой ячейке ту же позицию x, y кадра для каждого UITextField * (по-видимому, она переопределяется рамкой ячеек при ее отображении), поэтому, когда вы вызываете код 'scrollRectToVisible', он не выполняет похоже, имеют правильные координаты, которым он должен прокручиваться.
1) создайте ячейку и добавьте UITextField * в ячейку, используя значения x и y в кадре ячейки (я включаю здесь смещения, которые являются необязательными
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell* cell;
cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"UITableViewCell"] autorelease];
//this is the critical part: make sure your UITextField* frame is based on the frame of the cell in which it being placed.
UITextField* txtField = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.origin.x+20, cell.frame.origin.y+9, 280, 31)];
txtField.delegate = self;
[cell addSubview:txtField];
return cell;
}
2) отрегулируйте просмотр прокрутки в textFieldDidBeginEditing
-(void) textFieldDidBeginEditing:(UITextField *)textField {
CGRect textFieldRect = [textField frame];
[self.tableView scrollRectToVisible:textFieldRect animated:YES];
}
Ответ 10
Проблема усугубляется тем фактом, что нет простого способа узнать, прослушивал ли пользователь текстовое поле или активировался через becomeFirstResponder
.
Самое элегантное решение, которое я мог придумать, заключалось в том, чтобы реализовать подкласс hitTest:withEvent:
в ядре и в основном делать вид, что текстовое поле не существует, пока не будет выбрана ячейка.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [super hitTest:point withEvent:event];
if(view == self.textField && !self.selected) {
return self;
}
return view;
}
tableView:didSelectRowAtIndexPath:
, тогда необходимо вручную сделать текстовое поле первым ответчиком.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
TextFieldCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
[cell.textField becomeFirstResponder]
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
Наконец, мы должны отменить выбор строки, когда закончим редактирование. Это можно сделать с помощью делегата UITextField или с помощью уведомления о клавиатуре, независимо от того, что вы предпочитаете.
- (void)textFieldDidEndEditing:(UITextField *)textField {
[self.view endEditing:YES];
}
Ответ 11
у нас есть один контроллер под названием TPKeyboardAvoiding, он обрабатывает все, что касается динамической автоматической прокрутки для tableview и scrollview.
вы можете загрузить образец кода из кода ниже.
https://github.com/NarayanaRao35/TPKeyboardAvoiding