Получить UITableView для перехода к выбранному UITextField и избегать скрытия клавиатуры

У меня есть UITextField в представлении таблицы на UIViewController (не UITableViewController ). Если представление таблицы находится в UITableViewController , таблица автоматически прокручивается до редактируемого textField , чтобы предотвратить его скрытие с клавиатуры. Но на UIViewController это не так.

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

 -(void) textFieldDidBeginEditing:(UITextField *)textField { // SUPPOSEDLY Scroll to the current text field CGRect textFieldRect = [textField frame]; [self.wordsTableView scrollRectToVisible:textFieldRect animated:YES]; } 

Однако это только прокручивает таблицу до самой верхней строки. Кажется, что легкая задача – это пара дней разочарования.

Для построения ячеек tableView я использую следующее:

 - (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *identifier = [NSString stringWithFormat: @"%d:%d", [indexPath indexAtPosition: 0], [indexPath indexAtPosition:1]]; UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:identifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease]; cell.accessoryType = UITableViewCellAccessoryNone; UITextField *theTextField = [[UITextField alloc] initWithFrame:CGRectMake(180, 10, 130, 25)]; theTextField.adjustsFontSizeToFitWidth = YES; theTextField.textColor = [UIColor redColor]; theTextField.text = [textFieldArray objectAtIndex:indexPath.row]; theTextField.keyboardType = UIKeyboardTypeDefault; theTextField.returnKeyType = UIReturnKeyDone; theTextField.font = [UIFont boldSystemFontOfSize:14]; theTextField.backgroundColor = [UIColor whiteColor]; theTextField.autocorrectionType = UITextAutocorrectionTypeNo; theTextField.autocapitalizationType = UITextAutocapitalizationTypeNone; theTextField.clearsOnBeginEditing = NO; theTextField.textAlignment = UITextAlignmentLeft; //theTextField.tag = 0; theTextField.tag=indexPath.row; theTextField.delegate = self; theTextField.clearButtonMode = UITextFieldViewModeWhileEditing; [theTextField setEnabled: YES]; [cell addSubview:theTextField]; [theTextField release]; } return cell; } 

Я подозреваю, что могу заставить tableView правильно прокручивать, если можно каким-то образом передать indexPath.row в методе textFieldDidBeginEditing ?

Любая помощь приветствуется.

В моем приложении я успешно использовал комбинацию contentInset и scrollToRowAtIndexPath следующим образом:

Когда вы хотите отобразить клавиатуру, просто добавьте contentInset внизу с таблицей с нужной высотой:

 tableView.contentInset = UIEdgeInsetsMake(0, 0, height, 0); 

Затем вы можете безопасно использовать

 [tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:cell_index inSection:cell_section] animated:YES]; 

Добавляя contentInset, даже если вы фокусируетесь на последней ячейке, tableView по-прежнему сможет прокручиваться. Просто убедитесь, что, когда вы отклоняете клавиатуру, вы меняете содержимое.

РЕДАКТИРОВАТЬ:
Если у вас есть только один раздел (вы можете заменить cell_section на 0) и использовать тег textView, чтобы проинформировать строку ячейки.

Проверьте это для прокрутки UITextField над клавиатурой в UITableView ИЛИ UIScrollView

 - (void)keyboardWillShow:(NSNotification *)sender { CGFloat height = [[sender.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; NSTimeInterval duration = [[sender.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; UIViewAnimationOptions curveOption = [[sender.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16; [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState|curveOption animations:^{ UIEdgeInsets edgeInsets = UIEdgeInsetsMake(0, 0, height, 0); tableView.contentInset = edgeInsets; tableView.scrollIndicatorInsets = edgeInsets; }]; } - (void)keyboardWillHide:(NSNotification *)sender { NSTimeInterval duration = [[sender.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; UIViewAnimationOptions curveOption = [[sender.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16; [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState|curveOption animations:^{ UIEdgeInsets edgeInsets = UIEdgeInsetsZero; tableView.contentInset = edgeInsets; tableView.scrollIndicatorInsets = edgeInsets; }]; } 

И в - (void) viewDidLoad

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; 

затем

 - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } 

Это ответ на вопрос FunkyKat (большое спасибо FunkyKat!). Вероятно, было бы полезно не жестко кодировать UIEdgeInsetsZero для будущей совместимости с iOS.

Вместо этого я запрашиваю текущее значение вставки и при необходимости настраиваю нижнее значение.

 - (void)keyboardWillShow:(NSNotification *)sender { CGSize kbSize = [[[sender userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; NSTimeInterval duration = [[[sender userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; CGFloat height = UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]) ? kbSize.height : kbSize.width; if (isIOS8()) height = kbSize.height; [UIView animateWithDuration:duration animations:^{ UIEdgeInsets edgeInsets = [[self tableView] contentInset]; edgeInsets.bottom = height; [[self tableView] setContentInset:edgeInsets]; edgeInsets = [[self tableView] scrollIndicatorInsets]; edgeInsets.bottom = height; [[self tableView] setScrollIndicatorInsets:edgeInsets]; }]; } - (void)keyboardWillHide:(NSNotification *)sender { NSTimeInterval duration = [[[sender userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; [UIView animateWithDuration:duration animations:^{ UIEdgeInsets edgeInsets = [[self tableView] contentInset]; edgeInsets.bottom = 0; [[self tableView] setContentInset:edgeInsets]; edgeInsets = [[self tableView] scrollIndicatorInsets]; edgeInsets.bottom = 0; [[self tableView] setScrollIndicatorInsets:edgeInsets]; }]; } 

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

 - (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *identifier = [NSString stringWithFormat: @"%d:%d", [indexPath indexAtPosition: 0], [indexPath indexAtPosition:1]]; UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:identifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease]; UITextField *theTextField = [[UITextField alloc] initWithFrame:CGRectMake(180, 10, 130, 25)]; theTextField.keyboardType = UIKeyboardTypeDefault; theTextField.returnKeyType = UIReturnKeyDone; theTextField.clearsOnBeginEditing = NO; theTextField.textAlignment = UITextAlignmentLeft; // (The tag by indexPath.row is the critical part to identifying the appropriate // row in textFieldDidBeginEditing and textFieldShouldEndEditing below:) theTextField.tag=indexPath.row; theTextField.delegate = self; theTextField.clearButtonMode = UITextFieldViewModeWhileEditing; [theTextField setEnabled: YES]; [cell addSubview:theTextField]; [theTextField release]; } return cell; } -(void) textFieldDidBeginEditing:(UITextField *)textField { int z = textField.tag; if (z > 4) { // Only deal with the table row if the row index is 5 // or greater since the first five rows are already // visible above the keyboard // resize the UITableView to fit above the keyboard self.wordsTableView.frame = CGRectMake(0.0,44.0,320.0,200.0); // adjust the contentInset wordsTableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 10); // Scroll to the current text field [wordsTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:z inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } } - (BOOL)textFieldShouldEndEditing:(UITextField *)textField { // Determine which row is being edited int z = textField.tag; if (z > 4) { // resize the UITableView to the original size self.wordsTableView.frame = CGRectMake(0.0,44.0,320.0,416.0); // Undo the contentInset wordsTableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0); } return YES; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { // Dismisses the keyboard when the "Done" button is clicked [textField resignFirstResponder]; return YES; } 

Попробуйте мое кодирование, это поможет ypu

 tabelview.contentInset = UIEdgeInsetsMake(0, 0, 210, 0); [tableview scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:your_indexnumber inSection:Your_section] atScrollPosition:UITableViewScrollPositionMiddle animated:NO]; 

У Apple есть официальный пост, объясняющий, как это сделать, как и в UITableViewController. Мой ответ Stackoverflow объясняет это вместе с быстрой версией.

https://stackoverflow.com/a/31869898/1032179

Мне нужно было простое решение, поэтому мне помогли :

 func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { let pointInTable = textField.superview!.convert(textField.frame.origin, to: tableView) var tableVContentOffset = tableView.contentOffset tableVContentOffset.y = pointInTable.y if let accessoryView = textField.inputAccessoryView { tableVContentOffset.y -= accessoryView.frame.size.height } tableView.setContentOffset(tableVContentOffset, animated: true) return true; } 

введите описание изображения здесь

Вам нужно resize самого tableView так, чтобы он не попадал под клавиатуру.

 -(void) textFieldDidBeginEditing:(UITextField *)textField { // SUPPOSEDLY Scroll to the current text field self.worldsTableView.frame = CGRectMake(//make the tableView smaller; to only be in the area above the keyboard); CGRect textFieldRect = [textField frame]; [self.wordsTableView scrollRectToVisible:textFieldRect animated:YES]; } 

В качестве альтернативы вы можете использовать уведомление клавиатуры; это работает немного лучше, потому что у вас больше информации и более последовательна с точки зрения знания при приближении клавиатуры:

 //ViewDidLoad [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; 

И затем выполните:

 - (void)keyboardWillShow:(NSNotification *)notification { } - (void)keyboardWillHide:(NSNotification *)notification { } 

Мой код. Может быть, кому-то будет полезно: пользовательская ячейка textField в tableView

.m

  @property (nonatomic, strong) UITextField *currentCellTextField; CustomCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2]; if (cell == nil) { NSArray * nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil]; cell = (CustomCell *)[nib objectAtIndex:0]; cell.textfield.delegate = self; } - (void) textFieldDidBeginEditing:(UITextField *)textField { self.currentCellTextField = textField; CGPoint pnt = [self.organisationTableView convertPoint:textField.bounds.origin fromView:textField]; NSIndexPath* path = [self.organisationTableView indexPathForRowAtPoint:pnt]; if (path.section >= 2) { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.3]; self.organisationTableView.contentInset = UIEdgeInsetsMake(0, 0, kOFFSET_FOR_KEYBOARD, 0); CGPoint siize = self.organisationTableView.contentOffset; siize.y =(pnt.y-170); self.organisationTableView.contentOffset = CGPointMake(0, siize.y); [UIView commitAnimations]; } } -(BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; CGPoint pnt = [self.organisationTableView convertPoint:textField.bounds.origin fromView:textField]; NSIndexPath* path = [self.organisationTableView indexPathForRowAtPoint:pnt]; if (path.section >= 2) { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.3]; self.organisationTableView.contentInset = UIEdgeInsetsZero; self.organisationTableView.contentOffset = CGPointMake(0, self.organisationTableView.contentOffset.y); [UIView commitAnimations]; } return YES; } 

В моем случае мой UITableview находился внутри другого UIView и что UIvie был в основном UIScrollview. Поэтому я использовал более общее решение для таких проблем. Я просто нашел координату Y моей ячейки в конкретном UIScrollView и затем прокрутил до правильной точки:

 -(void)textFieldDidBeginEditing:(UITextField *)textField{ float kbHeight = 216;//Hard Coded and will not support lanscape mode UITableViewCell *cell = (UITableViewCell *)[textField superview]; float scrollToHeight = [self FindCordinate:cell]; [(UIScrollView *)self.view setContentOffset:CGPointMake(0, scrollToHeight - kbHeight + cell.frame.size.height) animated:YES]; } -(float)FindCordinate:(UIView *)cell{ float Ycordinate = 0.0; while ([cell superview] != self.view) { Ycordinate += cell.frame.origin.y; cell = [cell superview]; } Ycordinate += cell.frame.origin.y; return Ycordinate; } 

Другим простым решением является добавление дополнительного пространства для нижнего колонтитула последнего раздела таблицы:

 - (float)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { if (section == lastSection) { return keyboard height; } return 0; } 

Мы также можем добавить наш значок в эту область. 🙂

Вы можете попробовать добавить UITableViewController в UIViewController, а не только в виде таблицы. Таким образом вы можете вызвать UITableViewController viewWillAppear, и все будет работать.

Пример:

 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [tableViewController viewWillAppear:animated]; } 

У меня есть небольшая функция для ответов @FunkyKat и @bmauter (отличный ответ, кстати, он должен быть принят)

Регулярные вставки в виде таблицы Table сохраняются до / после появления клавиатуры.

 - (void)keyboardWillShow:(NSNotification *)sender { CGSize kbSize = [[[sender userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; NSTimeInterval duration = [[[sender userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; CGFloat height = UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]) ? kbSize.width : kbSize.height; [UIView animateWithDuration:duration animations:^{ UIEdgeInsets edgeInsets = self.tableView.contentInset; edgeInsets.bottom += height; self.tableView.contentInset = edgeInsets; edgeInsets = self.tableView.scrollIndicatorInsets; edgeInsets.bottom += height; self.tableView.scrollIndicatorInsets = edgeInsets; }]; } - (void)keyboardWillHide:(NSNotification *)sender { CGSize kbSize = [[[sender userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; NSTimeInterval duration = [[[sender userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; CGFloat height = UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]) ? kbSize.width : kbSize.height; [UIView animateWithDuration:duration animations:^{ UIEdgeInsets edgeInsets = self.tableView.contentInset; edgeInsets.bottom -= height; self.tableView.contentInset = edgeInsets; edgeInsets = self.tableView.scrollIndicatorInsets; edgeInsets.bottom -= height; self.tableView.scrollIndicatorInsets = edgeInsets; }]; } 
  • Как определить текущую нажатую клавишу?
  • Пользовательская «клавиатура», встроенная в приложение на Android
  • Отображать мягкую клавиатуру iPhone, даже если подключена аппаратная клавиатура
  • OSX: Обнаруживать общесистемные события KeyDown?
  • Java KeyListener заикается
  • iPhone UIWebview: как заставить цифровую клавиатуру? Является ли это возможным?
  • Как убрать клавиатуру для UITextView с ключом возврата?
  • Клавиатура iMessage Receding в приложении iOS
  • UISearchbar clearButton заставляет клавиатуру появляться
  • Получение размеров мягкой клавиатуры
  • Как resize UITextView на iOS при появлении клавиатуры?
  • Давайте будем гением компьютера.