티스토리 뷰

iOS

iOS 키보드 높이 확인하기 - keyboardFrameEndUserInfoKey

꿀벌의달콤한여행 2021. 4. 12. 22:43

iOS에서 키보드가 올라오면, 뷰의 컨텐츠를 가리는 경우가 있다. 그래서 키보드의 높이에 따라서 뷰의 컨텐츠 위치를 재조정해줘야하는데, 이때 주로 사용하는 방법이

  1. UIWindow.keyboardWillShowNotification 에 observer를 달고
  2. notification의 userinfo 키로 UIResponder.keyboardFrameEndUserInfoKey 를 사용하여 키보드의 높이를 가져와서 뷰 컨텐츠의 높이를 재조정해준다.

keyboardFrameEndUserInfoKey 는 별 게 아니고, UIResponder에 정의된 String 타입의 클래스 프로퍼티이다. 직접 코드를 타고 들어가보면 알 수 있다.

Notification.userInfo 가 딕셔너리 타입이라 키값을 위해 미리 정의해둔 듯

예시 코드

  1. UIWindow.keyboardWillShowNotification 에 observer를 달고
  2. NotificationCenter.default.addObserver( self, selector: #selector(LoginViewController.keyboardWillShow(_:)), name: UIWindow.keyboardWillShowNotification, object: nil )
  3. notification의 userinfo 키로 UIResponder.keyboardFrameEndUserInfoKey 를 사용하여 키보드의 높이를 가져와서 뷰 컨텐츠의 높이를 재조정해준다.
  4. @objc func keyboardWillShow(_ notification: Notification) { guard let keyboardFrameBegin = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return } let keyboardFrameBeginRect = keyboardFrameBegin.cgRectValue // 뷰 컨텐츠의 높이를 재조정 }

keyboardFrameBeginUserInfoKeykeyboardFrameEndUserInfoKey 차이

keyboardFrameBeginUserInfoKey, keyboardFrameEndUserInfoKey 둘 다 값은 동일하게 키보드 사이즈 값이 나오는데 전자의 경우 맨 처음을 제외하고는 height가 줄어서 나왔다. 정상적인 동작을 원한다면 후자를 사용하자(원인을 정확하게 모르겠네요 ㅠㅠ)

그리고 keyboardFrameBeginUserInfoKey는 키보드가 등장하는 순간이기 때문에, origin 값이 (0, 뷰의 높이값) 이다. 반면 keyboardFrameEndUserInfoKey는 키보드가 등장을 마친 후이기 때문에 origin 값이 (0, 키보드 높이값)이다. 키보드 뷰가 생성되고 밑에서 위로 밀듯이 올라온다고 생각하면 될 것 같다.

UIWindow.keyboardWillShowNotification 알림 시기

UIWindow.keyboardWillShowNotification는 이미 키보드가 있더라도, 다른 textField를 클릭하거나 tabRecognizer가 적용된 뷰를 터치하는 등의 행위를 했을 때에도 호출이 된다. 그래서 keyboardShown 등과 같은 Bool 타입 변수를 사용해 옵저버의 타겟함수 내에서 키보드가 현재 나타나있는지 없는지를 판단해주자.

이러한 것을 고려하고, 샌드버드의 예시코드를 참고한 최종 예시와 코드는 아래와 같다(스크롤뷰를 활용함).

스크롤뷰를 활용함

    @objc func keyboardWillShow(_ notification: Notification) {
        guard let keyboardFrameBegin = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
        let keyboardFrameBeginRect = keyboardFrameBegin.cgRectValue

        if !self.keyboardShown {
            let distanceFromBottom = self.view.frame.height - self.LoginButton.frame.maxY
            if distanceFromBottom <= keyboardFrameBeginRect.size.height + 90 {
                animateUI(keyboardFrameBeginRect.size.height)
            }
        }
        self.keyboardShown = true
    }
    func animateUI(_ scrollValue: CGFloat) {
        self.view.layoutIfNeeded()
        self.scrollViewBottom.constant = scrollValue

        let animator = UIViewPropertyAnimator(duration: 0.3, curve: .easeOut) {
            self.userIdLabelTop.constant = !self.keyboardShown ? 23 : 56
            self.view.layoutIfNeeded()
            self.versionInfoLabel.alpha = self.keyboardShown ? 1 : 0
        }
        animator.startAnimation()
        logoInvisible = !logoInvisible
    }

예시 코드는 constraint를 아울렛변수로 사용하여 컨텐츠들의 위치를 재조정해주고 있다. 특히 self.scrollViewBottom.constant 값을 재조정해주며 versionInfoLabel.alpha 값을 애니메이션해주는 것이 되게 미려했다. 나도 나중에 써먹어야지 헤헤.

참고자료

developer.apple.com/library/archive/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

댓글