Разработка iPhone/iPod touch приложений: Полезности – UIToolBar над UIKeyboard

keyboard

Клавиатура с UIToolBar'ом

Много кто видел как в некоторых приложениях вместе с клавиатурой выезжает UIToolBar – примерно так, как это показано на рисунке.

Есть несколько вариантов так сделать. Первый, и самый “простой” – это позиционировать UIToolBar в нужное место до/или после того, как началось редактирование, и клавиатура должна выехать. Даже для начинающего программиста эта задача не составит особого труда.

Программист более продвинутый, который любит и умеет читать документацию или искать, без особого труда найдет , что можно подписаться на глобальные события UIKeyboardWillShowNotification и UIKeyboardWillHideNotification, чтобы вовремя подставлять/убирать UIToolBar.

После того, как нам не понравится (а нам  не понравится) то, что UIToolBar “прыгает” вместо того, чтобы плавно уезжать вместе с клавиатурой, добавим немного анимации. После таких манипуляций должен получиться примерно следующий код:


// Здесб у нас будут "константы"
#define VIEWPORT_SIZE 320
#define KEYBOARD_HEIGHT 215
#define TOOLBAR_HEIGHT 44
#define KEYBOARD_TRANSITION_DURATION 0.3

// Подписываемся на глобальные события
- (void)viewDidLoad {
[super viewDidLoad];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
// Событие перед появлением клавиатуры
[nc addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
// Событие перед скрытием клавиатуры
[nc addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

-(void) keyboardWillShow:(NSNotification *) note {
// Так как клавиатура появляется с самого низа экрана,
// то UIToolBar должен быть чуть-чуть выше
toolBar.frame = CGRectMake(0, [[self view] frame ].size.height - TOOLBAR_HEIGHT, VIEWPORT_SIZE, TOOLBAR_HEIGHT);

// Вычисляем точку, куда должен "прилететь" UIToolBar
CGRect toolBarRect = [toolBar  frame];
toolBarRect.origin.y = [[self view] frame].size.height - KEYBOARD_HEIGHT - TOOLBAR_HEIGHT;

// Добавляем красивости
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:KEYBOARD_TRANSITION_DURATION];
[toolBar setFrame:toolBarRect];
[UIView commitAnimations];

}

-(void) keyboardWillHide:(NSNotification *) note {
//А вот "улетать" UIToolBar должен за пределы экрана.
//Он будет "улетать" чуть-чуть быстрее, чем клавиатура
//Выглядит неплохо, хоть и не совсем правильно.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:KEYBOARD_TRANSITION_DURATION];
toolBar.frame = CGRectMake(0, [[self view] frame ].size.height, VIEWPORT_SIZE, TOOLBAR_HEIGHT);
[UIView commitAnimations];
}

Это, если использовать “константы”. Трудно себе представить, конечно, но что будет, если вдруг размер клавиатуры/время ее появляения/анимация ее появления вдруг изменятся? Как делать все правильно? Обращаю внимание, что в большинстве случаев вполне достаточно кода который уже был приведен, и я сам считаю, что “Що занадто – то нездраво”(“Что чересчур – то нездорово”). Но если все-таки надо, то вышеперечисленную информацию можно “достать” из NSNotification userInfo. userInfo – это, обычно, NSDictionary, который по ключам хранит полезную информацию:


//Тип анимации
//   UIKeyboardAnimationCurveUserInfoKey = 0;
//Время анимации ("выезд клавиатуры")
//   UIKeyboardAnimationDurationUserInfoKey = 0.300000011920929;
//Размеры клавиатуры
//   UIKeyboardBoundsUserInfoKey = NSRect: {{0, 0}, {320, 216}};
//Центр клавиатуры в начале анимации
//   UIKeyboardCenterBeginUserInfoKey = NSPoint: {160, 588};
//Центр клавиатуры в конце анимации
//   UIKeyboardCenterEndUserInfoKey = NSPoint: {160, 372};

...

// А вот, собвственно, как віглядит код:

-(void) keyboardWillShow:(NSNotification *) note {
   NSDictionary * userInfo = [note userInfo];
   CGRect keyboardSize;
   [[userInfo objectForKey:UIKeyboardBoundsUserInfoKey] getValue:&keyboardSize];
   CGPoint keyboardCenterBeforeAnimation;
   [[userInfo objectForKey:UIKeyboardCenterBeginUserInfoKey] getValue:&keyboardCenterBeforeAnimation];
   CGPoint keyboardCenterAfterAnimation;
   [[userInfo valueForKey:UIKeyboardCenterEndUserInfoKey] getValue:&keyboardCenterAfterAnimation];
   double animationDuration;
   [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
   int animationType;
   [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationType];

   toolBar.frame = CGRectMake(0, keyboardCenterBeforeAnimation.y - keyboardSize.size.height / 2 - TOOLBAR_HEIGHT, keyboardSize.size.width, TOOLBAR_HEIGHT);
   [UIView beginAnimations:nil context:nil];
   [UIView setAnimationDuration:animationDuration];
   [UIView setAnimationCurve:animationType];
   [toolBar setFrame:CGRectMake(0, keyboardCenterAfterAnimation.y - keyboardSize.size.height / 2 - TOOLBAR_HEIGHT, keyboardSize.size.width, TOOLBAR_HEIGHT)];
   [UIView commitAnimations];
}

Теперь вы знаете своего врага в лицо – и вся информация о нем есть. Как использовать эту информацию – решать вам ;) Я дал лишь один из вариантов ее использования ;)

И не забывайте, что у клавиатуры и ее событий есть некоторые особенности.

Комментарии

Antivirus

в 18:45, 01.02.2010

Очень интересная статья, давно искал манула, как писать под UIKeyboard. Автору респект.

olgerd

в 2:15, 12.03.2010

спасибо, пригодилось)

зы: еще нужно незабывать отписываться от нотификейшинов, когда они тебе не нужны… например:
[[NSNotificationCenter defaultCenter] removeObserver:self];

иначе можно натолкнуться на мелкие неприятности :) на чем я и попался

Павел Тайкало

в 10:12, 12.03.2010

Спасибо, подправлю ;)

Оставить комментарий