Получить 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]; }
Однако это только прокручивает таблицу до самой верхней строки. Кажется, что легкая задача – это пара дней разочарования.
- Java System-Wide Keyboard Shortcut
- Обнаружение текущего языка ввода iPhone
- Нажмите клавиши клавиатуры с помощью командного файла
- Обложки iPhone для iPhone UITextField
- iPhone - Клавиатура скрывает TextField
Для построения ячеек 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
?
Любая помощь приветствуется.
- Слушайте нажатие клавиши, когда программа находится в фоновом режиме
- OSX: Обнаруживать общесистемные события KeyDown?
- Создание SoftKeyboard с несколькими / альтернативными символами на ключ
- Пользовательская «клавиатура», встроенная в приложение на Android
- Пользовательская клавиатура iOS 8: изменение высоты
- iOS 8.1 Симулятор всегда использует раскладку клавиатуры США, несмотря на немецкую аппаратную клавиатуру
- Java KeyListener заикается
- Клавиатура iMessage Receding в приложении iOS
В моем приложении я успешно использовал комбинацию 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 объясняет это вместе с быстрой версией.
Мне нужно было простое решение, поэтому мне помогли :
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; }]; }