it-swarm.com.ru

Перемещайте клавиатуру вверх при редактировании UITextField на iOS9

Чтобы мои клавиатуры перемещались вверх, чтобы раскрыть UITextField в моем приложении для iOS, я использовал следующий ответ: https://stackoverflow.com/a/6908258/3855618 на iOS7 и 8, и на данный момент он работает отлично. Однако на iOS 9.1 это больше не работает.

Чтобы быть более точным, даже если фоновое представление перемещается вверх, UITextField нет.

Есть идеи, что так сильно изменилось со времен iOS9 и iOS 9.1?

14
Gannicus

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

От официального Apple doc :

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

Корректировка вашего контента обычно включает в себя временное изменение размера одного или нескольких представлений и расположение их так, чтобы текстовый объект оставался видимым. Самый простой способ управления текстовыми объектами с помощью клавиатуры - это встроить их в объект UIScrollView (или в один из его подклассов, таких как UITableView). Когда отображается клавиатура, все, что вам нужно сделать, это сбросить область содержимого представления прокрутки и прокрутить нужный текстовый объект в нужное положение. Таким образом, в ответ на UIKeyboardDidShowNotification ваш метод-обработчик будет делать следующее:

  1. Получите размер клавиатуры.
  2. Отрегулируйте нижнюю вставку содержимого представления прокрутки по высоте клавиатуры.
  3. Прокрутите целевое текстовое поле в поле зрения.
 // Called when the UIKeyboardDidShowNotification is sent.
- (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);
   scrollView.contentInset = contentInsets;
   scrollView.scrollIndicatorInsets = contentInsets;

   // If active text field is hidden by keyboard, scroll it so it's visible
   // Your app might not need or want this behavior.
   CGRect aRect = self.view.frame;
   aRect.size.height -= kbSize.height;
   if (!CGRectContainsPoint(aRect, activeField.frame.Origin) ) {
     [self.scrollView scrollRectToVisible:activeField.frame animated:YES];
   }
}

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
   UIEdgeInsets contentInsets = UIEdgeInsetsZero;
   scrollView.contentInset = contentInsets;
   scrollView.scrollIndicatorInsets = contentInsets;
}
36
Istvan

Ноль строк кода

Без хаков, клуджей, обходных путей и слушателей.

Настоящий вопрос задавался много раз начиная с рассвета времени iOS. Ни один ответ на StackOverflow не пережил более двух итераций iOS. Это правильно, потому что UIKit постоянно меняется из-под ваших ног. Существует дизайн, в отличие от реализация решения этой древней проблемы. Используйте UITableViewController.

Используйте UITableViewController

Когда UITableView управляется UITableViewController, прокрутка управляется автоматически для вас. Никогда не возиться с UIKeyboardWillShowNotification, никогда. Просто создайте статический или динамический UITableViewCells для макета вашего интерфейса, добавьте UITextView или UITextField по мере необходимости; просто стать первым респондентом прокрутить нужное место.

@availability (iOS, введено = 2.0)

 UITableViewController

Заметки

  1. Работает на все iOS с 2.0.
  2. Цитата: «Не теряйте времени на оптимизацию плохого алгоритма; выберите лучший»
  3. См. https://stackoverflow.com/a/32390936/218152 .
8
SwiftArchitect

Нам нужно взять кадр клавиатуры из уведомления. При получении ссылки на scrollView, tableView и т.д. Преобразование нижней границы обзора в координаты окна. Когда мы определим, насколько клавиатура покрывает наш взгляд, и если разница больше 0, мы можем добавить вставку ниже. Попробуйте этот код:

- (void)subscribeKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}

- (void)unsubscribeKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillShowNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillHideNotification
                                                  object:nil];
}


- (void)keyboardWillShow:(NSNotification *)aNotification
{
    CGRect keyBoardFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

    UIWindow *keyWindow = [[[UIApplication sharedApplication] delegate] window];

    UIScrollView *someScrollView = ......

    CGPoint tableViewBottomPoint = CGPointMake(0, CGRectGetMaxY([someScrollView bounds]));
    CGPoint convertedTableViewBottomPoint = [someScrollView convertPoint:tableViewBottomPoint
                                                                           toView:keyWindow];

    CGFloat keyboardOverlappedSpaceHeight = convertedTableViewBottomPoint.y - keyBoardFrame.Origin.y;

    if (keyboardOverlappedSpaceHeight > 0)
    {
        UIEdgeInsets tableViewInsets = UIEdgeInsetsMake(0, 0, keyboardOverlappedSpaceHeight, 0);
        [someScrollView setContentInset:tableViewInsets];
    }
}

- (void)keyboardWillHide:(NSNotification *)aNotification
{
    UIEdgeInsets tableViewInsets = UIEdgeInsetsZero;
    UIScrollView *someScrollView = ......

    [someScrollView setContentInset:tableViewInsets];
}
3
NixSolutionsMobile

я последовал за документом от @Istvan на сайт Apple, и для его работы не хватает многих вещей:
1. Установите для документа .h значение <UITextFieldDelegate> (чтобы иметь возможность работать с «активным полем»)
2. В viewDidLoad установите делегатов для ваших UITextfields и установите высоту содержимого прокрутки с большей высотой (в моем случае я установил еще 500):

CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height + 500;
_scrollView.contentSize = CGSizeMake(screenWidth, screenHeight);

И теперь все работает ...

1
Rwakos

Добавьте все UITextField на UIScrollView и используйте TPKeyboardAvoiding

1
Varun Naharia

Я обычно слушаю уведомления клавиатуры и делаю соответствующие изменения в макете. Смотрите мой другой ответ для более подробной информации и пример проекта.

1
NKorotkov

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

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    [self didBeginEditingIn:textField];
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self didEndEditing];
}


static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216+100;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162+100;

- (void)didBeginEditingIn:(UIView *)view
{
    CGRect textFieldRect = [self.view.window convertRect:view.bounds fromView:view];
    CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];

    CGFloat midline = textFieldRect.Origin.y + 0.5* textFieldRect.size.height;
    CGFloat numerator = midline - viewRect.Origin.y- MINIMUM_SCROLL_FRACTION * viewRect.size.height;
    CGFloat denominator = (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)* viewRect.size.height;
    CGFloat heightFraction = numerator / denominator;

    if (heightFraction < 0.0)
    {
        heightFraction = 0.0;
    }
    else if (heightFraction > 1.0)
    {
        heightFraction = 1.0;
    }

    UIInterfaceOrientation orientation =
    [[UIApplication sharedApplication] statusBarOrientation];
    if (orientation == UIInterfaceOrientationPortrait ||
        orientation == UIInterfaceOrientationPortraitUpsideDown)
    {
        _animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
    }
    else
    {
        _animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
    }

    CGRect viewFrame = self.view.frame;
    viewFrame.Origin.y -= _animatedDistance;

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

    [self.view setFrame:viewFrame];

    [UIView commitAnimations];
}

- (void)didEndEditing
{
    CGRect viewFrame = self.view.frame;
    viewFrame.Origin.y += _animatedDistance;

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

    [self.view setFrame:viewFrame];

    [UIView commitAnimations];
}
1
Nishant