Вандад Нахавандипур - iOS. Приемы программирования
// содержащий (в координатах экрана) начало и конец области, которую
// занимает на дисплее виртуальная клавиатура.
// Пользуйтесь различными возможностями convertRect, относящимися к UIView и UIWindow, чтобы получить контур клавиатуры в желаемой системе
// координат. Анимационные пары «ключ/значение» доступны лишь для
// уведомлений, относящихся к семейству «will»
UIKIT_EXTERN NSString *const UIKeyboardWillShowNotification;
UIKIT_EXTERN NSString *const UIKeyboardDidShowNotification;
UIKIT_EXTERN NSString *const UIKeyboardWillHideNotification;
UIKIT_EXTERN NSString *const UIKeyboardDidHideNotification;
Это код Apple. Мы написали наш код точно таким же образом. Apple предоставляет уведомления, отправляемые системой, а затем документирует их. Вам понадобится сделать нечто подобное. При создании уведомлений, посылаемых компонентами, находящимися внутри вашего приложения, обязательно документируйте эти уведомления и объясняйте другим программистам (в частности, коллегам, работающим с вами в одной команде), каковы типичные значения, содержащиеся в пользовательском словаре такого уведомления, а также сообщайте им всю прочую важную информацию о ваших уведомлениях.
15.3. Слушание уведомлений, поступающих с клавиатуры, и реагирование на них
Постановка задачи
Мы позволяем пользователю вводить какой-либо текст в нашем графическом интерфейсе. Для этого применяется определенный компонент, например текстовое поле или текстовый вид, требующий наличия клавиатуры. Тем не менее если всплывающая на экране виртуальная клавиатура заслоняет половину пользовательского интерфейса, то она практически бесполезна. Подобной ситуации необходимо избегать.
Решение
Нужно слушать уведомления, поступающие от клавиатуры, и перемещать компоненты пользовательского интерфейса вверх или вниз либо полностью перегруппировывать их так, чтобы пользователь мог видеть нужную ему часть графического интерфейса, даже если клавиатура и занимает половину экрана. Сами уведомления, посылаемые клавиатурой, подробнее рассматриваются в подразделе «Обсуждение» данного раздела.
Обсуждение
У устройств, работающих с операционной системой iOS, нет физической клавиатуры. Но у них есть виртуальная клавиатура, всплывающая на экране всякий раз, когда пользователь должен ввести текст в какое-нибудь текстовое поле (UITextField, см. раздел 1.19) или текстовый вид (UITextView, см. раздел 1.20). На iPad пользователь даже может делить клавиатуру на части и перемещать их вверх и вниз. Есть несколько пограничных случаев, о которых, вам, возможно, придется позаботиться при проектировании пользовательского интерфейса. Можете обратиться к помощи дизайнеров пользовательских интерфейсов (если в вашей компании есть такие специалисты) и рассказать им, что на iPad пользователь может делить клавиатуру на части. Перед тем как приступать к творческой работе, они должны об этом узнать. В этом разделе мы коснемся подобного пограничного случая.
Сначала рассмотрим, как выглядит клавиатура в iPhone. Виртуальная клавиатура может отображаться в книжной или альбомной ориентации. В книжной ориентации клавиатура iPhone выглядит так, как на рис. 15.1.
Рис. 15.1. Клавиатура на iPhone, книжная ориентация
А клавиатура в альбомной ориентации на iPhone будет выглядеть так, как на рис. 15.2.
Рис. 15.2. Клавиатура в iPhone, альбомная ориентация
Но на iPad клавиатура выглядит немного иначе. Самое очевидное отличие заключается в том, что эта клавиатура гораздо крупнее, чем на iPhone, поскольку сам экран у iPad шире. При альбомной ориентации клавиатура iPad значительно шире, но на ней содержится тот же набор клавиш, что и при книжной ориентации. Кроме того, пользователь может при желании «разбирать» клавиатуру iPad на части. Благодаря этому он лучше контролирует функционирование клавиатуры, зато появляются дополнительные проблемы у программистов, дизайнеров пользовательских интерфейсов и пользовательских взаимодействий.
iOS широковещательно распространяет различные уведомления, касающиеся отображения клавиатуры на экране. Вот список этих уведомлений и краткие характеристики каждого из них:
• UIKeyboardWillShowNotification — распространяется, когда клавиатура вот-вот появится на экране. Уведомление несет с собой словарь с пользовательской информацией, в котором содержатся различные данные о клавиатуре, анимации, которая будет применяться при выводе клавиатуры на экран, и другая информация;
• UIKeyboardDidShowNotification — распространяется, когда клавиатура уже появилась на экране;
• UIKeyboardWillHideNotification — распространяется, когда клавиатура вот-вот будет убрана с экрана. Уведомление несет с собой словарь с пользовательской информацией, в котором содержатся различные данные о клавиатуре, анимации, которая будет применяться при уходе клавиатуры с экрана, длительности анимации и т. д.;
• UIKeyboardDidHideNotification — распространяется после того, как клавиатура полностью скроется с экрана.
Уведомления UIKeyboardWillShowNotification и UIKeyboardWillHideNotification несут с собой словари с пользовательской информацией. В этих словарях содержатся валидные ключи и значения. Далее перечислены те из ключей, которые могут быть вам интересны:
• UIKeyboardAnimationCurveUserInfoKey — значение этого ключа характеризует тип анимационной кривой, которая будет использоваться при выводе клавиатуры на экран или ее скрытии. Этот ключ содержит значение типа NSNumber (инкапсулированное в объекте типа NSValue), которое, в свою очередь, содержит беззнаковое целое типа NSUInteger;
• UIKeyboardAnimationDurationUserInfoKey — значение данного ключа указывает в секундах длительность анимации, применяемой при отображении или скрытии клавиатуры. Если клавиатура вот-вот будет отображена, то это будет рамка, в которой появится клавиатура. Если клавиатура уже есть на экране, это будет контур, обрамляющий клавиатуру на экране перед тем, как она уйдет с экрана. Этот ключ содержит значение типа CGRect (инкапсулированное в объекте типа NSValue);
• UIKeyboardFrameBeginUserInfoKey — значение данного ключа указывает размеры рамки клавиатуры до того, как начнется анимация. Если клавиатура вот-вот отобразится, то перед появлением клавиатуры появится эта рамка. Если клавиатура в данный момент отображена и вот-вот уйдет с экрана, это будет рамка, фактически занимаемая клавиатурой на экране, прежде чем клавиатура уйдет с экрана в сопровождении соответствующей анимации. Этот ключ содержит значение типа CGRect (инкапсулированное в объект типа NSValue);
• UIKeyboardFrameEndUserInfoKey — значение данного ключа описывает контур клавиатуры, который оформится после того, как будет применена анимация. Если клавиатура вот-вот появится на экране, то она займет именно этот контур. Если клавиатура уходит с экрана, то именно этот контур от нее освободится. Этот ключ содержит значение типа CGRect (инкапсулированное в объекте типа NSValue).
Рассмотрим пример. Мы собираемся создать простое приложение с единственным видом. Это приложение будет работать только на iPhone. В нем будут отображаться вид с изображением и текстовое поле. Текстовое поле находится в нижней части экрана. Итак, когда пользователь дотрагивается до текстового поля, чтобы ввести в него некоторый текст, на экране всплывает виртуальная клавиатура, полностью заслоняющая текстовое поле. Наша задача — анимировать содержимое вида и перераспределить элементы так, чтобы все они оставались видимыми, даже если экран наполовину закрыт клавиатурой. В этом приложении мы будем использовать раскадровки. В контроллере вида заполним вид с изображением, поместив в него прокручивающийся вид, и поместим в этом прокручивающемся виде и вид с изображением, и текстовое поле (рис. 15.3).
Рис. 15.3. Простая раскадровка, содержащая вид с изображением и текстовое поле
Прокручивающийся вид в данном примере является родительским видом как для вида с изображением, так и для текстового поля. Он целиком заполняет пространство своего родительского вида.
Я уже прикрепил прокручивающийся вид, вид с изображением и текстовое поле, определенные в раскадровке, к файлу реализации контроллера вида, вот так:
#import «ViewController.h»
@interface ViewController () <UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UITextField *textField;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
…
Теперь, когда аутлеты прикреплены к свойствам в контроллере нашего вида, можно приступить к слушанию клавиатурных уведомлений: