[iOS] keyboard通知介紹

使用App時,很常會遇到text field的處理問題,相信大家都看過點擊text view或text field時,畫面可能會往上移動,以讓使用者可以看到text view並且輸入鍵盤,處理畫面的移動幾乎是必然會遇到的事情了。下面的相關通知名稱的資訊可以參考官方文件

鍵盤出現和消失,通常是使用notification機制來得知的,當鍵盤出現或消失時,要執行相對應的動作,而跟鍵盤有關的通知有以下六個:

  • UIKeyboardWillShowNotification
  • UIKeyboardDidShowNotification
  • UIKeyboardWillHideNotification
  • UIKeyboardDidHideNotification 
  • UIKeyboardWillChangeFrameNotification 
  • UIKeyboardDidChangeFrameNotification
仔細看動詞的時態的話,有Will/Did兩種,兩兩成對。Show跟Hide意思很明顯,就是說鍵盤將/已經出現/隱藏,後兩者是會在鍵盤的frame改變之前/之後進行通知。

鍵盤出現隱藏的作法大致如下:
  1. 在viewDidLoad或是viewDidAppear裡面加入通知,標記接收到通知時要啟動的方法。
  2. 實作對應的方法。
  3. 記得在dealloc內取消通知,ARC可不協助處理取消註冊。
通常會註冊的通知是Will的,這是因為對應的方法會使用UIView的動畫去改變frame,而如果你是註冊Did通知,動畫會延遲一下才進行,這是因為要等到鍵盤已經出現/隱藏才會執行方法。

再來我先介紹一下鍵盤通知裡面包含的資訊,在userInfo裡面:
  • UIKeyboardFrameBeginUserInfoKey:裡面的CGRect是鍵盤出現的動畫一開始時,鍵盤在螢幕上的CGRect,但如果螢幕有旋轉,旋轉造成的改變不會算在內
  • UIKeyboardFrameEndUserInfoKey:裡面的CGRect是鍵盤出現的動畫結束後,鍵盤呈現在螢幕上的CGRect,實際上我們會使用這個值來獲得鍵盤的尺寸資訊。
  • UIKeyboardAnimationCurveUserInfoKey:可獲得鍵盤出現動畫的UIViewAnimationCurve常數。
  • UIKeyboardAnimationDurationUserInfoKey:可獲得動畫的時間長度。
所以我們可以使用鍵盤通知裡面包含的訊息來製作我們的動畫。

正式的寫法大概如下:

- (void)viewDidLoad {
    // .......
    // ......
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];

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




- (void)keyboardWillShow:(NSNotification *)notification
{
    [self moveUp:YES withInfo:[notification userInfo]];
}

- (void)keyboardWillHide:(NSNotification *)notification
{
    [self moveUp:NO withInfo:[notification userInfo]];
}

- (void)moveUp:(BOOL)isUp withInfo:(NSDictionary *)userInfo
{
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
    double timeInterval = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect frame = self.view.frame;
   
    frame.origin.y -= (isUp?keyboardSize.height : 0);

    [UIView animateWithDuration:timeInterval delay:0 options:(curve<<16) animations:^{
        self.view.frame = frame;
    }completion:nil];   
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

簡單介紹一下,我們會透過兩個方法(keyboardWillShow 和 keyboardWillHide),和專門處理動畫的方法作溝通,當然你也可以作一個property封裝keyboard出現與否的訊息,這樣可能可以更短一點。我這樣寫的好處是完全使用鍵盤的動畫參數,因此動畫看起來是同步。

留言