ios - when - uitableview keyboard contentinset




Выполнение прокрутки UITableView при выборе текстового поля (20)

Если вы используете UITableViewController вместо UIViewController, он автоматически сделает это.

После долгих проб и ошибок я сдаюсь и задаю вопрос. Я видел много людей с подобными проблемами, но не могу получить ответы на все правильно.

У меня есть UITableView который состоит из пользовательских ячеек. Ячейки состоят из 5 текстовых полей рядом друг с другом (вроде сетки).

Когда я пытаюсь прокручивать и редактировать ячейки в нижней части UITableView , я не могу правильно расположить ячейки над клавиатурой.

Я видел много ответов, рассказывающих об изменении размеров и т. Д. ... но ни один из них не работал до сих пор.

Может ли кто-нибудь прояснить «правильный» способ сделать это с помощью конкретного примера кода?


Если вы можете использовать UITableViewController , вы получаете бесплатную функциональность. Иногда, однако, это не вариант, особенно если вам нужно несколько просмотров, а не только UITableView .

Некоторые из представленных здесь решений не работают на iOS ≥4, некоторые не работают на iPad или в ландшафтном режиме, некоторые не работают для клавиатур Bluetooth (там, где мы не хотим прокрутки), некоторые не работают работа при переключении между несколькими текстовыми полями. Поэтому, если вы выберете какое-либо решение, обязательно проверьте эти случаи. Это решение, которое мы используем в InAppSettingsKit :

- (void)_keyboardWillShow:(NSNotification*)notification {
    if (self.navigationController.topViewController == self) {
        NSDictionary* userInfo = [notification userInfo];

        // we don't use SDK constants here to be universally compatible with all SDKs ≥ 3.0
        NSValue* keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardBoundsUserInfoKey"];
        if (!keyboardFrameValue) {
            keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardFrameEndUserInfoKey"];
        }

        // Reduce the tableView height by the part of the keyboard that actually covers the tableView
        CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds;
        if (UIInterfaceOrientationLandscapeLeft == self.interfaceOrientation ||UIInterfaceOrientationLandscapeRight == self.interfaceOrientation ) {
            windowRect = IASKCGRectSwap(windowRect);
        }
        CGRect viewRectAbsolute = [_tableView convertRect:_tableView.bounds toView:[[UIApplication sharedApplication] keyWindow]];
        if (UIInterfaceOrientationLandscapeLeft == self.interfaceOrientation ||UIInterfaceOrientationLandscapeRight == self.interfaceOrientation ) {
            viewRectAbsolute = IASKCGRectSwap(viewRectAbsolute);
        }
        CGRect frame = _tableView.frame;
        frame.size.height -= [keyboardFrameValue CGRectValue].size.height - CGRectGetMaxY(windowRect) + CGRectGetMaxY(viewRectAbsolute);

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
        [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
        _tableView.frame = frame;
        [UIView commitAnimations];

        UITableViewCell *textFieldCell = (id)((UITextField *)self.currentFirstResponder).superview.superview;
        NSIndexPath *textFieldIndexPath = [_tableView indexPathForCell:textFieldCell];

        // iOS 3 sends hide and show notifications right after each other
        // when switching between textFields, so cancel -scrollToOldPosition requests
        [NSObject cancelPreviousPerformRequestsWithTarget:self];

        [_tableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
    }
}

- (void) scrollToOldPosition {
  [_tableView scrollToRowAtIndexPath:_topmostRowBeforeKeyboardWasShown atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

- (void)_keyboardWillHide:(NSNotification*)notification {
    if (self.navigationController.topViewController == self) {
        NSDictionary* userInfo = [notification userInfo];

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
        [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
        _tableView.frame = self.view.bounds;
        [UIView commitAnimations];

        [self performSelector:@selector(scrollToOldPosition) withObject:nil afterDelay:0.1];
    }
}   

Вот полный код класса в InAppSettingsKit. Чтобы протестировать его, используйте дочернюю панель «Полный список», где вы можете протестировать описанные выше сценарии.


Мой подход:

Я первый подкласс UITextField и добавляю свойство indexPath. В cellFor ... Метод я передаю свойство indexPath.

Затем я добавляю следующий код:

UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:textField.indexPath];

CGPoint cellPoint = [cell convertPoint:textField.center toView:self.tableView];
[UIView animateWithDuration:0.3 animations:^(void){self.tableView.contentOffset = CGPointMake(0, cellPoint.y-50);}];

к текстуFieldShould / WillBegin ... и т. д.

Когда Клавиатура исчезает, вы должны отменить ее:

[UIView animateWithDuration:0.3 animations:^(void){self.tableView.contentOffset = CGPointMake(0, 0);}];

Надеюсь, вы, ребята, уже получили решение, читая все это. Но я нашел решение следующим образом. Я ожидаю, что у вас уже есть ячейка с UITextField . Поэтому при подготовке просто держите индекс строки в теге текстового поля.

cell.textField.tag = IndexPath.row;

Создайте activeTextField , экземпляр UITextField с глобальной областью, как UITextField ниже:

@interface EditViewController (){

    UITextField *activeTextField;

}

Итак, теперь вы просто скопируете мой код в конце. Кроме того, не забудьте добавить UITextFieldDelegate

#pragma mark - TextField Delegation

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{

    activeTextField = textField;

    return YES;
}

- (void)textFieldDidEndEditing:(UITextField *)textField{

    activeTextField = nil;

}

Регистрирует notifications клавиатуре

#pragma mark - Keyboard Activity

- (void)registerForKeyboardNotifications

{

    [[NSNotificationCenter defaultCenter] addObserver:self

                                         selector:@selector(keyboardWasShown:)

                                             name:UIKeyboardDidShowNotification object:nil];



    [[NSNotificationCenter defaultCenter] addObserver:self

                                         selector:@selector(keyboardWillBeHidden:)

                                             name:UIKeyboardWillHideNotification object:nil];



}

Ручки Notifications клавиатуры:

Вызывается, когда UIKeyboardDidShowNotification .

- (void)keyboardWasShown:(NSNotification*)aNotification

{

    NSDictionary* info = [aNotification userInfo];

    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);

    [self.tableView setContentInset:contentInsets];

    [self.tableView setScrollIndicatorInsets:contentInsets];

    NSIndexPath *currentRowIndex = [NSIndexPath indexPathForRow:activeTextField.tag inSection:0];

    [self.tableView scrollToRowAtIndexPath:currentRowIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];

}

Вызывается, когда UIKeyboardWillHideNotification

- (void)keyboardWillBeHidden:(NSNotification*)aNotification

{

    UIEdgeInsets contentInsets = UIEdgeInsetsZero;

    [self.tableView setContentInset:contentInsets];

    [self.tableView setScrollIndicatorInsets:contentInsets];

}

Теперь осталось одно: ViewDidLoad метод registerForKeyboardNotifications метод ViewDidLoad следующим образом:

- (void)viewDidLoad {

    [super viewDidLoad];

    // Registering keyboard notification

    [self registerForKeyboardNotifications];

    // Your codes here...

}

Вы закончили, надеюсь, что ваши textFields больше не будут скрыты клавиатурой.


Простейшее решение для Swift :

override func viewDidLoad() {
    super.viewDidLoad()

    searchBar?.becomeFirstResponder()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MyViewController.keyboardWillShow(_:)), name: UIKeyboardDidShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MyViewController.keyboardWillHide(_:)), name: UIKeyboardDidHideNotification, object: nil)
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardWillShow(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        if let keyboardHeight = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue.size.height {
            tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)
        }
    }
}

func keyboardWillHide(notification: NSNotification) {
    UIView.animateWithDuration(0.2, animations: { self.table_create_issue.contentInset = UIEdgeInsetsMake(0, 0, 0, 0) })
    // For some reason adding inset in keyboardWillShow is animated by itself but removing is not, that's why we have to use animateWithDuration here
    }

У меня была такая же проблема, но я заметил, что она появляется только в одном представлении. Поэтому я начал искать различия в контроллерах.

Я узнал, что поведение прокрутки задано в - (void)viewWillAppear:(BOOL)animated из супер-экземпляра.

Поэтому обязательно выполните следующие действия:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    // your code
}

И не имеет значения, используете ли вы UIViewController или UITableViewController ; проверил его, поставив UITableView в качестве подзаголовка self.view в UIViewController . Это было одно и то же поведение. В представлении не разрешалось прокручивать, если вызов [super viewWillAppear:animated]; скучал.


Я делаю что-то очень похожее, это родовое, не нужно вычислять что-то конкретное для вашего кода. Просто проверьте замечания по коду:

В MyUIViewController.h

@interface MyUIViewController: UIViewController <UITableViewDelegate, UITableViewDataSource>
{
     UITableView *myTableView;
     UITextField *actifText;
}

@property (nonatomic, retain) IBOutlet UITableView *myTableView;
@property (nonatomic, retain) IBOutlet UITextField *actifText;

- (IBAction)textFieldDidBeginEditing:(UITextField *)textField;
- (IBAction)textFieldDidEndEditing:(UITextField *)textField;

-(void) keyboardWillHide:(NSNotification *)note;
-(void) keyboardWillShow:(NSNotification *)note;

@end

В MyUIViewController.m

@implementation MyUIViewController

@synthesize myTableView;
@synthesize actifText;

- (void)viewDidLoad 
{
    // Register notification when the keyboard will be show
    [[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector(keyboardWillShow:)
                                          name:UIKeyboardWillShowNotification
                                          object:nil];

    // Register notification when the keyboard will be hide
    [[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector(keyboardWillHide:)
                                          name:UIKeyboardWillHideNotification
                                          object:nil];
}

// To be link with your TextField event "Editing Did Begin"
//  memoryze the current TextField
- (IBAction)textFieldDidBeginEditing:(UITextField *)textField
{
    self.actifText = textField;
}

// To be link with your TextField event "Editing Did End"
//  release current TextField
- (IBAction)textFieldDidEndEditing:(UITextField *)textField
{
    self.actifText = nil;
}

-(void) keyboardWillShow:(NSNotification *)note
{
    // Get the keyboard size
    CGRect keyboardBounds;
    [[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];

    // Detect orientation
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    CGRect frame = self.myTableView.frame;

    // Start animation
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:0.3f];

    // Reduce size of the Table view 
    if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
        frame.size.height -= keyboardBounds.size.height;
    else 
        frame.size.height -= keyboardBounds.size.width;

    // Apply new size of table view
    self.myTableView.frame = frame;

    // Scroll the table view to see the TextField just above the keyboard
    if (self.actifText)
      {
        CGRect textFieldRect = [self.myTableView convertRect:self.actifText.bounds fromView:self.actifText];
        [self.myTableView scrollRectToVisible:textFieldRect animated:NO];
      }

    [UIView commitAnimations];
}

-(void) keyboardWillHide:(NSNotification *)note
{
    // Get the keyboard size
    CGRect keyboardBounds;
    [[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];

    // Detect orientation
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    CGRect frame = self.myTableView.frame;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:0.3f];

    // Increase size of the Table view 
    if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
        frame.size.height += keyboardBounds.size.height;
    else 
        frame.size.height += keyboardBounds.size.width;

    // Apply new size of table view
    self.myTableView.frame = frame;

    [UIView commitAnimations];
}

@end

Версия Swift 1.2+:

class ViewController: UIViewController, UITextFieldDelegate {
    @IBOutlet weak var activeText: UITextField!
    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: Selector("keyboardWillShow:"),
            name: UIKeyboardWillShowNotification,
            object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: Selector("keyboardWillHide:"),
            name: UIKeyboardWillHideNotification,
            object: nil)
    }

    func textFieldDidBeginEditing(textField: UITextField) {
        activeText = textField
    }

    func textFieldDidEndEditing(textField: UITextField) {
        activeText = nil
    }

    func keyboardWillShow(note: NSNotification) {
        if let keyboardSize = (note.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            var frame = tableView.frame
            UIView.beginAnimations(nil, context: nil)
            UIView.setAnimationBeginsFromCurrentState(true)
            UIView.setAnimationDuration(0.3)
            frame.size.height -= keyboardSize.height
            tableView.frame = frame
            if activeText != nil {
                let rect = tableView.convertRect(activeText.bounds, fromView: activeText)
                tableView.scrollRectToVisible(rect, animated: false)
            }
            UIView.commitAnimations()
        }
    }

    func keyboardWillHide(note: NSNotification) {
        if let keyboardSize = (note.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            var frame = tableView.frame
            UIView.beginAnimations(nil, context: nil)
            UIView.setAnimationBeginsFromCurrentState(true)
            UIView.setAnimationDuration(0.3)
            frame.size.height += keyboardSize.height
            tableView.frame = frame
            UIView.commitAnimations()
        }
    }
}

Я думаю, что я придумал решение, чтобы соответствовать поведению приложений Apple.

Во-первых, в вашем представленииWillAppear: подписаться на уведомления о клавиатуре, так что вы знаете, когда клавиатура покажет и скроется, и система сообщит вам размер клавиатуры, но не забывайте отменить регистрацию в своем представленииWillDisappear :.

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

Внедрите методы, подобные приведенным ниже, чтобы вы отрегулировали размер вашего TableView, чтобы он соответствовал видимой области, как показывает клавиатура. Здесь я отслеживаю состояние клавиатуры отдельно, поэтому я могу выбрать, когда сама установка tableView вернется на полную высоту, так как вы получаете эти уведомления при каждом изменении поля. Не забудьте реализовать keyboardWillHide: и выберите где-нибудь подходящее, чтобы исправить размер tableView.

-(void) keyboardWillShow:(NSNotification *)note
{
    CGRect keyboardBounds;
    [[note.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] getValue: &keyboardBounds];
    keyboardHeight = keyboardBounds.size.height;
    if (keyboardIsShowing == NO)
    {
        keyboardIsShowing = YES;
        CGRect frame = self.view.frame;
        frame.size.height -= keyboardHeight;

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationBeginsFromCurrentState:YES];
        [UIView setAnimationDuration:0.3f];
        self.view.frame = frame;
        [UIView commitAnimations];
    }
}

Теперь вот бит прокрутки, сначала мы разрабатываем несколько размеров, затем видим, где мы находимся в видимой области, и устанавливаем прямоугольник, который мы хотим прокрутить, чтобы быть либо полуразложением выше или ниже середины текстового поля где он находится в поле зрения. В этом случае у нас есть массив UITextFields и перечисление, которое отслеживает их, поэтому умножение rowHeight на номер строки дает нам фактическое смещение кадра в этом внешнем виде.

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    CGRect frame = textField.frame;
    CGFloat rowHeight = self.tableView.rowHeight;
    if (textField == textFields[CELL_FIELD_ONE])
    {
        frame.origin.y += rowHeight * CELL_FIELD_ONE;
    }
    else if (textField == textFields[CELL_FIELD_TWO])
    {
        frame.origin.y += rowHeight * CELL_FIELD_TWO;
    }
    else if (textField == textFields[CELL_FIELD_THREE])
    {
        frame.origin.y += rowHeight * CELL_FIELD_THREE;
    }
    else if (textField == textFields[CELL_FIELD_FOUR])
    {
        frame.origin.y += rowHeight * CELL_FIELD_FOUR;
    }
    CGFloat viewHeight = self.tableView.frame.size.height;
    CGFloat halfHeight = viewHeight / 2;
    CGFloat midpoint = frame.origin.y + (textField.frame.size.height / 2);
    if (midpoint < halfHeight)
    {
        frame.origin.y = 0;
        frame.size.height = midpoint;
    }
    else
    {
        frame.origin.y = midpoint;
        frame.size.height = midpoint;
    }
    [self.tableView scrollRectToVisible:frame animated:YES];
}

Кажется, это работает очень хорошо.


Другой простой метод (работает только с одним разделом)

//cellForRowAtIndexPath
UItextField *tf;
[cell addSubview:tf];
tf.tag = indexPath.row;
tf.delegate = self;

//textFieldDidBeginEditing:(UITextField *)text
[[self.tableView scrollToRowsAtIndexPath:[NSIndexPath indexPathForRow:text.tag in section:SECTIONINTEGER] animated:YES];

Если ваш UITableView управляется подклассом UITableViewController, а не UITableView, а делегатом текстового поля является UITableViewController, он должен автоматически управлять всей прокруткой - все эти другие комментарии очень сложно реализовать на практике.

Для хорошего примера см. Проект кода примера apple: TaggedLocations.

Вы можете видеть, что он прокручивается автоматически, но, похоже, не существует кода, который делает это. В этом проекте также есть пользовательские таблицы представления таблиц, поэтому, если вы создаете приложение с ним в качестве руководства, вы должны получить желаемый результат.


ПРАВЫЙ ОТВЕТ - ответ Сэма Хо:

«Если вы используете UITableViewController вместо UIViewController, он автоматически сделает это».

Просто убедитесь, что вы подключили свой UITableView к свойству TableView UITableViewController (поэтому, например, не добавляйте его в качестве подзадачи свойства View для UITableViewController).

Также не забудьте установить свойство AutoresizingMask вашего UITableView в FlexibleHeight


Поскольку у вас есть текстовые поля в таблице, лучшим способом является изменение размера таблицы - вам нужно установить, что tableView.frame будет меньше по высоте на размер клавиатуры (я думаю, около 165 пикселей), а затем развернуть его снова, когда клавиатура отклоняется.

В то же время вы также можете отключить взаимодействие с пользователем для tableView, если вы не хотите прокручивать пользователя.


Этот солетон работает для меня, ПОЖАЛУЙСТА, обратите внимание на линию

[tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height+160) animated:YES];

Вы можете изменить значение 160, чтобы оно соответствовало вам.

- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGRect bkgndRect = activeField.superview.frame;
                        bkgndRect.size.height += kbSize.height;
     [activeField.superview setFrame:bkgndRect];
     [tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height+160) animated:YES];
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
   activeField = textField;
}
-(void)textFieldDidEndEditing:(UITextField *)textField
 {
     activeField = nil;
 }
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    tableView.contentInset = contentInsets;
    tableView.scrollIndicatorInsets = contentInsets;
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGRect bkgndRect = activeField.superview.frame;
    //bkgndRect.size.height += kbSize.height;
    [activeField.superview setFrame:bkgndRect];
    [tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height) animated:YES];
}

Я столкнулся с чем-то вроде вашей проблемы (мне нужен экран, похожий на настройки iPhone iPhone .app с кучей редактируемых ячеек, уложенных поверх другого) и обнаружил, что этот подход хорошо работает:

скользящие uitextfields вокруг, чтобы избежать


UITextField's delegateМетод использования :

стриж

func textFieldShouldBeginEditing(textField: UITextField) -> bool {
  let txtFieldPosition = textField.convertPoint(textField.bounds.origin, toView: yourTableViewHere)
  let indexPath = yourTablViewHere.indexPathForRowAtPoint(txtFieldPosition)
  if indexPath != nil {
     yourTablViewHere.scrollToRowAtIndexPath(indexPath!, atScrollPosition: .Top, animated: true)
  }
  return true
}

Objective-C

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
  CGPoint txtFieldPosition = [textField convertPoint:CGPointZero toView: yourTablViewHere];
  NSLog(@"Begin txtFieldPosition : %@",NSStringFromCGPoint(txtFieldPosition));
  NSIndexPath *indexPath = [yourTablViewHere indexPathForRowAtPoint:txtFieldPosition];

  if (indexPath != nil) {
     [yourTablViewHere scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
  }
  return YES;
}

Более поточное решение. Он вписывается в методы делегата UITextField, поэтому он не требует беспорядочного ввода сообщений w / UIKeyboard.

Замечания по внедрению:

kSettingsRowHeight - высота UITableViewCell.

offsetTarget и offsetThreshold передаются с помощью kSettingsRowHeight. Если вы используете другую высоту строки, установите эти значения в свойство y точки. [alt: рассчитать смещение строки другим способом.]

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
CGFloat offsetTarget    = 113.0f; // 3rd row
CGFloat offsetThreshold = 248.0f; // 6th row (i.e. 2nd-to-last row)

CGPoint point = [self.tableView convertPoint:CGPointZero fromView:textField];

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.2];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

CGRect frame = self.tableView.frame;
if (point.y > offsetThreshold) {
    self.tableView.frame = CGRectMake(0.0f,
                      offsetTarget - point.y + kSettingsRowHeight,
                      frame.size.width,
                      frame.size.height);
} else if (point.y > offsetTarget) {
    self.tableView.frame = CGRectMake(0.0f,
                      offsetTarget - point.y,
                      frame.size.width,
                      frame.size.height);
} else {
    self.tableView.frame = CGRectMake(0.0f,
                      0.0f,
                      frame.size.width,
                      frame.size.height);
}

[UIView commitAnimations];

return YES;

}

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];

[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.2];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

CGRect frame = self.tableView.frame;
self.tableView.frame = CGRectMake(0.0f,
                  0.0f,
                  frame.size.width,
                  frame.size.height);

[UIView commitAnimations];

return YES;

}


Если вы используете Three20, используйте autoresizesForKeyboardсвойство. Просто установите в свой -initWithNibName:bundleметод контроллера вида

self.autoresizesForKeyboard = YES

Это позаботится:

  1. Прослушивание уведомлений клавиатуры и настройка рамы в виде таблицы
  2. Прокрутка до первого ответчика

Сделано и сделано.


Если вы используете uitableview для размещения текстовых полей ( от Jeff Lamarche ), вы можете просто прокрутить табличное представление, используя метод делегата.

(Примечание: мои текстовые поля хранятся в массиве с тем же индексом, что и строка в представлении таблицы)

- (void) textFieldDidBeginEditing:(UITextField *)textField
    {

        int index;
        for(UITextField *aField in textFields){

            if (textField == aField){
                index = [textFields indexOfObject:aField]-1;
            }
        }

         if(index >= 0) 
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];

        [super textFieldDidBeginEditing:textField];
    }

Пример в Swift, используя точную точку текстового поля из Get indexPath UITextField в UITableViewCell со Swift :

func textFieldDidBeginEditing(textField: UITextField) {
    let pointInTable = textField.convertPoint(textField.bounds.origin, toView: self.accountsTableView)
    let textFieldIndexPath = self.accountsTableView.indexPathForRowAtPoint(pointInTable)
    accountsTableView.scrollToRowAtIndexPath(textFieldIndexPath!, atScrollPosition: .Top, animated: true)
}

Сообщения о клавиатуре работают, но пример кода Apple для этого предполагает, что представление прокрутки является корневым представлением окна. Обычно это не так. Вы должны компенсировать полосы вкладок и т. Д., Чтобы получить правильное смещение.

Это проще, чем кажется. Вот код, который я использую в UITableViewController. Он имеет две переменные экземпляра, hiddenRect и keyboardShown.

// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification {
    if (keyboardShown)
        return;

    NSDictionary* info = [aNotification userInfo];

    // Get the frame of the keyboard.
    NSValue *centerValue = [info objectForKey:UIKeyboardCenterEndUserInfoKey];
    NSValue *boundsValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
    CGPoint keyboardCenter = [centerValue CGPointValue];
    CGRect keyboardBounds = [boundsValue CGRectValue];
    CGPoint keyboardOrigin = CGPointMake(keyboardCenter.x - keyboardBounds.size.width / 2.0,
                                         keyboardCenter.y - keyboardBounds.size.height / 2.0);
    CGRect keyboardScreenFrame = { keyboardOrigin, keyboardBounds.size };


    // Resize the scroll view.
    UIScrollView *scrollView = (UIScrollView *) self.tableView;
    CGRect viewFrame = scrollView.frame;
    CGRect keyboardFrame = [scrollView.superview convertRect:keyboardScreenFrame fromView:nil];
    hiddenRect = CGRectIntersection(viewFrame, keyboardFrame);

    CGRect remainder, slice;
    CGRectDivide(viewFrame, &slice, &remainder, CGRectGetHeight(hiddenRect), CGRectMaxYEdge);
    scrollView.frame = remainder;

    // Scroll the active text field into view.
    CGRect textFieldRect = [/* selected cell */ frame];
    [scrollView scrollRectToVisible:textFieldRect animated:YES];

    keyboardShown = YES;
}


// Called when the UIKeyboardDidHideNotification is sent
- (void)keyboardWasHidden:(NSNotification*)aNotification
{
    // Reset the height of the scroll view to its original value
    UIScrollView *scrollView = (UIScrollView *) self.tableView;
    CGRect viewFrame = [scrollView frame];
    scrollView.frame = CGRectUnion(viewFrame, hiddenRect);

    keyboardShown = NO;
}




scroll