Нажатие на UITextField в UITableViewCell - PullRequest
19 голосов
/ 08 декабря 2008

У меня есть проблема, когда при нажатии textField в UITableViewCell метод tableView:didSelectRowAtIndexPath: не вызывается. Проблема в том, что мне нужно прокрутить мой tableView в правильное положение, в противном случае клавиатура переместится прямо на первого респондента.

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

[[self tableView] scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];

в мой tableView метод делегата и в UITextField делегат метод textFieldDidBeginEditing:.

Является ли лучший способ просто создать новый метод, передать ему indexPath ячейки / текстового поля, по которому выполняется щелчок, и вызвать метод из делегата tableView и из делегата UITextField? лучший способ сделать это?

Ответы [ 11 ]

22 голосов
/ 30 сентября 2011

Я нашел следующее работает хорошо (предполагается, что вы находитесь в контроллере табличного представления)

- (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];
}
9 голосов
/ 02 марта 2009

Есть несколько способов решить эту проблему. Что происходит, так это то, что tableViewCell делегирует событие touch своим подпредставлениям, что заставляет текстовое поле обрабатывать касание вместо вашей ячейки.

Чтобы это исправить:

  • Установите для свойства userinteractionEnabled в пользовательском поле UITe значение NO, затем, когда вы получите сообщение didSelectRowAtIndexPath, вы повторно активируете userInteractionEnabled и вызовете становление TextField становиться становящимся атрибутом. На v2.2 вам даже не нужно устанавливать флаг userInteractionEnabled, я не проверял это с другими версиями, однако в документации совершенно ясно, что вы должны включить это. в tableViewController вам просто нужно сохранить indexpath, пока вы не получите сообщение UIKeyboardDidShow

  • Создайте делегат для UITextField, который отчитывается перед вашим tableViewController, чтобы вы могли установить смещение прокрутки оттуда.

  • зарегистрировать события клавиатуры, а затем определить смещение прокрутки, проверив, какое текстовое поле находится в режиме редактирования

6 голосов
/ 09 декабря 2008

Вы можете установить свой контроллер в качестве делегата вашего UITextField, а затем настроить представление таблицы в textFieldDidBeginEditing: или textFieldShouldBeginEditing:

3 голосов
/ 07 мая 2011

Я обнаружил, что на самом деле это довольно легко сделать.

Метод делегата UITextField textFieldDidBeginEditing предоставит вам текстовое поле, которое затем можно сопоставить с indexPath, используя:

self.currentIndexPath = [self.tableView indexPathForRowAtPoint:textField.frame.origin];

Затем вы можете прокрутить ячейку в поле зрения (т.е. в вашем обработчике уведомлений клавиатуры UIKeyboardDidShowNotification):

[self.tableView scrollToRowAtIndexPath:self.currentIndexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
3 голосов
/ 28 октября 2010

Я нашел решение.

  1. Открыть файл .xib в конструкторе интерфейсов.
  2. Выберите вид таблицы
  3. В меню IB выберите Инструменты-> Инспектор размеров В разделе Размер представления прокрутки измените значение Вставка -> Нижнее значение до 100, 150, 250 в зависимости от размера вашего представления таблицы.

Код

-(void) textFieldDidBeginEditing:(UITextField *)textField 
{
    UITableViewCell *cell = (UITableViewCell *) [[textField superview] superview];
    [self.tableView scrollToRowAtIndexPath:[tableView indexPathForCell:cell]
    atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
3 голосов
/ 08 января 2010

Я не нашел ни одного решения, которое бы работало на меня в сети. После нескольких дней поисков в Google и экспериментов, я наконец-то выпустил этот документ с хорошей прибылью. Это сложная ошибка в Apple iPhone, как вы увидите в конце этого поста.

Если вы столкнулись с такой проблемой, как я, то:

  1. с размером ячейки таблицы больше половины экрана iphone (не путайте с примерами Apple UICatalog с короткой ячейкой таблицы менее 50 точек, здесь не применимо),

  2. имеющий более одного поля uitex в ячейке или комбинацию поля uitextview и uitextview или uiwebview в ячейке,

  3. Нажатие между полями uitextview и uitextview или uiwebview приводит к непредсказуемой позиции прокрутки, либо выбранное поле uitext выскакивает из поля зрения или закрывается клавиатурой. Он работает только в первый раз, когда клавиатура появляется в ячейке просмотра таблицы и впоследствии не работает правильно.

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

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

Чтобы восстановить tableView назад, вам нужно добавить наблюдателя в 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 через несколько месяцев.

1 голос
/ 28 марта 2012

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 к себе

0 голосов
/ 23 декабря 2015

у нас есть один контроллер с именем TPKeyboardAvoiding , он обрабатывает все, что касается динамической автоматической прокрутки для просмотра таблиц и просмотра прокрутки. Вы можете скачать пример кода из кода ниже. https://github.com/NarayanaRao35/TPKeyboardAvoiding

0 голосов
/ 04 августа 2015

Проблема усугубляется тем, что нет простого способа узнать, нажал ли пользователь текстовое поле или оно было активировано с помощью 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];
}
0 голосов
/ 09 июня 2009

Я боролся с этой же проблемой, когда у меня есть 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's 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];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...