Как управлять поведением клавиатуры в приложениях iOS

Подружитесь с экранной клавиатурой и пользовательским интерфейсом приложения

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

В этой статье вы познакомитесь с некоторыми из наших опытов по обеспечению бесперебойной работы макета приложения Azimo для iOS с экранной клавиатурой.

Вначале давайте взглянем на API, предоставляемый Apple в UIKit. Мы можем зарегистрировать наблюдателей в NotificationCenter, который будет уведомлять нас об изменении рамки клавиатуры:

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

UIKeyboardBoundsUserInfoKey устарел, и вам не следует его использовать!

Наиболее распространенное решение для обработки внешнего вида клавиатуры - это регистрация уведомлений UIResponder.keyboardWillShowNotification и UIResponder.keyboardWillHideNotification в экземпляре ViewController. А затем обновите макет для каждого вызова, обновив вставки в представлении прокрутки.

Этот подход хорош, если у вас есть только одно место в приложении с полями ввода пользователя. Когда у вас будет больше таких мест, вам нужно скопировать и вставить код и настроить его.

Чтобы не создавать шаблонов, мы можем полагаться на другое решение UIKit - Safe Area.

Безопасная зона - это руководство по макету, которое показывает доступное пространство для контента вашего приложения. Чтобы использовать его, вы можете подключить к нему свои представления и положиться на AutoLayout, чтобы обрабатывать все изменения за вас. Safe Area учитывает такие вещи, как панели навигации, поэтому вы можете быть уверены, что они никогда не перекрывают ваш контент.

Почему бы тогда не сообщить Safe Area о размере клавиатуры, чтобы механизм AutoLayout обрабатывал ее внешний вид за нас?

К сожалению, создать такой код невозможно:

Это потому, что свойство UIView.safeAreaInsets доступно только для чтения.

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

KeyboardAppearListener, наше средство

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

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

Пока код очевиден. Мы регистрируемся для получения уведомлений UIResponder.keyboardWillShowNotification и UIResponder.keyboardWillHideNotification, которые вызывают наши внутренние функции.

Теперь давайте реализуем нашу keyboardWillShow функцию. Вначале нам нужно настроить охрану, чтобы убедиться, что все необходимые данные доступны:

Нам нужно получить начальный и конечный кадры и сравнить эти значения. Эта проверка не требуется, но нет смысла выполнять остальную логику, если ничего не изменилось. И это может происходить много раз, поскольку система отправляет уведомление каждый раз, когда пользователь нажимает на текстовое поле (даже то же самое).

Затем мы вычисляем новые вставки безопасной зоны для клавиатуры.

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

Нам нужно помнить, что система прикрепляет клавиатуру к нижнему краю экрана, и мы рассчитываем дополнительную безопасную зону. Это означает, что вычисленная нижняя врезка слишком велика. Чтобы исправить это, нам нужно вычесть нижнюю вставку безопасной области «окна». У нас нет прямого доступа к этому значению, но мы можем легко его вычислить. И, конечно же, мы хотим сделать это только один раз, поэтому нам нужно добавить новую переменную windowsSafeAreaWereAdded в наш класс.

Окончательная версия:

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

Тело функции keyboardWillHide практически идентично. Разница заключается в математике, которую мы используем для расчета дополнительных вставок безопасных областей.

Мы почти на месте. Код работает хорошо до тех пор, пока мы не поворачиваем устройство, пока клавиатура находится на экране. В этом случае наша математика больше не работает. Почему? Это из-за того, как iOS сообщает нам об изменении. Поток:

  1. пользователь вращает устройство
  2. система выполняет вращения
  3. система отправляет уведомление UIResponder.keyboardWillHideNotification ,
  4. система отправляет UIResponder.keyboardWillShowNotification уведомления.

Порядок этих шагов является ключевым здесь. После поворота нижний размер безопасной зоны будет другим. Если вы помните, мы рассчитываем безопасную зону каждый раз, когда нам нужно ее использовать. Это приводит к тому, что после поворота (когда выполняется скрытие клавиатуры) мы используем другое значение для windowSafeArea, чем было использовано для расчета дополнительной безопасной области. Чтобы исправить это, нам нужно сохранить ранее использованное значение в локальной переменной и использовать его вместо вычисления.

Теперь все, что вам нужно сделать, это создать экземпляр KeyboardAppearListener и хранить его, пока жив ваш контроллер представления.

Вот окончательная реализация нашего KeyboardAppearListener. Мы не создаем для него отдельный фреймворк, так как в классе меньше 90 строк.

P.S. Если вам не нравится тот факт, что мы должны изменить состояние, изменив windowSafeArea и windowsSafeAreaWereAdded, вы не одиноки. Я тоже не очень люблю это. Если у вас есть идея, как от него избавиться, напишите нам!

На пути к финансовым услугам, доступным для всех

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