iOS8에서 키보드 높이의 올바른 값을 얻을 수 없습니다.


83

이 코드를 사용하여 키보드의 크기를 결정했습니다.

- (void)keyboardWillChange:(NSNotification *)notification {
    NSDictionary* keyboardInfo = [notification userInfo];
    NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
    CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];

}

나는 이것을 시뮬레이터에서 실행하고있다.

문제는 iOS 8이기 때문에 키보드 제안이 올라 갔거나 아래로 밀면 다른 (올바른 것이 아님) 값을 얻습니다.

키보드 제안을 포함하여 키보드의 정확한 크기를 어떻게 얻을 수 있습니까?


keyboardFrameBeginRect로컬 좌표 로 변환하면 도움이 될 수 있습니다 .
rmaddy

@rmaddy 정말 중요하지 않습니다. 높이 만 필요합니다.
Eli Braginskiy 2014 년

방향에 따라 잘못 될 수 있습니다. iOS 8에서는 더 이상 문제가되지 않을 수 있지만 시도해보고 차이가 있는지 확인하십시오.
rmaddy

@rmaddy 나는 그것을 시도하지만 슬프게도하지 않았다 도움말
엘리 Braginskiy을

답변:


98

사용하다

NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];

좋은 대답입니다. 감사. 그 키를 사용해야한다는 것을 어떻게 알았습니까? @souvickcse
줄리안 오소리오에게

6
CGRect keyboardFrame = [keyboardFrameBegin CGRectValue];
Awesomeness 2014 년

12
너무 높은, 키보드는 여전히 258이었고, 나를 위해 일을하지 않았다
marchinram

@trycatchfinally 감사합니다
souvickcse

1
오늘 교훈을 배웠습니다. UIKeyboardFrameEndUserInfoKey와 UIKeyboardFrameBeginUserInfoKey에는 큰 차이가 있습니다. @souvickcse 주셔서 감사합니다
jejernig

120

iOS에 맞춤형 키보드가 도입되면서이 문제는 좀 더 복잡해졌습니다.

간단히 말해 UIKeyboardWillShowNotification 은 사용자 정의 키보드 구현에 의해 여러 번 호출 될 수 있습니다.

  1. Apple 시스템 키보드가 열려 있을 때 (세로)
    • UIKeyboardWillShowNotification은 키보드 높이 224로 전송됩니다.
  2. 있는 Swype 키보드 (세로) 열 :
    • UIKeyboardWillShowNotification이 키보드 높이 0으로 전송됩니다.
    • UIKeyboardWillShowNotification은 216 의 키보드 높이로 전송됩니다.
    • UIKeyboardWillShowNotification은 256 의 키보드 높이로 전송됩니다.
  3. SwiftKey 키보드 가 열릴 때 (세로) :
    • UIKeyboardWillShowNotification이 키보드 높이 0으로 전송됩니다.
    • UIKeyboardWillShowNotification은 216 의 키보드 높이로 전송됩니다.
    • UIKeyboardWillShowNotification은 키보드 높이 259로 전송됩니다.

이러한 시나리오를 하나의 코드 라인에서 적절하게 처리하려면 다음을 수행해야합니다.

UIKeyboardWillShowNotificationUIKeyboardWillHideNotification 알림 에 대해 관찰자를 등록합니다 .

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

현재 키보드 높이를 추적하는 전역 변수를 만듭니다.

CGFloat _currentKeyboardHeight = 0.0f;

키보드 높이의 현재 변경에 반응하도록 keyboardWillShow 를 구현합니다 .

- (void)keyboardWillShow:(NSNotification*)notification {
   NSDictionary *info = [notification userInfo];
   CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
   CGFloat deltaHeight = kbSize.height - _currentKeyboardHeight; 
   // Write code to adjust views accordingly using deltaHeight
   _currentKeyboardHeight = kbSize.height;
}

참고 : 뷰 오프셋에 애니메이션을 적용 할 수 있습니다. 정보 사전에서 키가 값이 포함되어 UIKeyboardAnimationDurationUserInfoKey을 . 이 값은 표시되는 키보드와 동일한 속도로 변경 사항을 애니메이션하는 데 사용할 수 있습니다.

reset _currentKeyboardHeight에 keyboardWillHide 를 구현 하고 해제되는 키보드에 반응합니다.

- (void)keyboardWillHide:(NSNotification*)notification {
   NSDictionary *info = [notification userInfo];
   CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
   // Write code to adjust views accordingly using kbSize.height
   _currentKeyboardHeight = 0.0f;
}

dgangsta, 귀하의 연구는 흥미롭지 만 질문의 문제는 FrameEnd 속성 대신 FrameBegin을 얻는 것입니다. 귀하의 답변에 따르면 델타 대신 애니메이션보기 메서드에 UIViewAnimationOptionBeginFromCurrentState 플래그를 사용하는 것을 고려 했습니까?
MikeR 2014

SwiftKey (v 1.2.3) 높이에 대해 259 대신 iOS8.1.3이 설치된 iPhone6 ​​+에서 271을 얻었습니다.
Hemang

2
여전히 작동하는 솔루션입니까? SwiftKey를 사용할 때 259 대신 44의 높이를 얻습니다.
KIDdAe

미친, 이것은 나를 도왔지만 이미 표시된 후 키보드 높이가 필요했기 때문에 대신 keyboardDidShow :를 관찰합니다. 이 맞춤형 키보드가 3 개의 알림을 트리거하는 반면 Apple은 하나만 트리거하는 이유는 무엇입니까? 일관성이없는 것 같습니다.
Liron Yahdav

나처럼 가로 모드에서 iPhone에 문제가있는 경우 프레임 END 키의 출처잘못 되었기 때문 입니다 (적어도 일반 iOS 10 키보드의 경우). KEYBOARD BEGIN RECT: (0.0, 375.0, 667.0, 162.0) ... KEYBOARD END RECT: (0.0, 213.0, 667.0, 162.0)
xaphod

18

StackOverflow 기사를 볼 때 까지이 문제가 발생했습니다 .

UIKeyboardFrameEndUserInfoKey 변환

convertRect기능 을 사용하여 키보드의 크기를 사용 가능한 크기로 변환하지만 화면 방향으로 변환하는 방법을 보여줍니다 .

NSDictionary* d = [notification userInfo];
CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];
r = [myView convertRect:r fromView:nil];

이전에, 내가 사용하는 아이 패드 앱을 가지고 UIKeyboardFrameEndUserInfoKey있지만 하지 않은 사용을 convertRect, 그리고 벌금을했다.

그러나 iOS 8에서는 더 이상 제대로 작동하지 않습니다. 갑자기 iPad에서 가로 모드로 실행되는 키보드의 높이1024 픽셀 이라고보고했습니다 .

따라서 이제 iOS 8에서는이 convertRect기능 을 사용해야 합니다.


iOS8 이전 키보드 직사각형은 항상 세로 방향 화면 좌표였습니다. 가로 모드에서 높이와 너비를 수동으로 바꾸는 코드를 추가했지만 키보드 직사각형 방향이보기 방향과 일치하는 iOS 8에서 깨졌습니다. convertRect 솔루션은 iOS 7 또는 iOS 8에 대해 올바른 결과를 제공합니다.
user1055568

7

Swift 2.0으로 작성된 dgangsta의 솔루션 과 유사합니다 .

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardWillShow(notification: NSNotification) {
    guard let kbSizeValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
    guard let kbDurationNumber = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber else { return }
    animateToKeyboardHeight(kbSizeValue.CGRectValue().height, duration: kbDurationNumber.doubleValue)
}

func keyboardWillHide(notification: NSNotification) {
    guard let kbDurationNumber = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber else { return }
    animateToKeyboardHeight(0, duration: kbDurationNumber.doubleValue)
}

func animateToKeyboardHeight(kbHeight: CGFloat, duration: Double) {
    // your custom code here
}

퀵 타입과 스마일리를 표시 / 숨길 때 문제
user3722523

이것은 소스였습니다. Swift 2.3의 사소한 차이점이지만 컴파일러의 자동 완성 제안이므로 문제가 없습니다.
Ethan Parker

5

내가 할 extension에 대한UIViewController

extension UIViewController {
    func keyboardWillChangeFrameNotification(notification: NSNotification, scrollBottomConstant: NSLayoutConstraint) {
        let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
        let curve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber
        let keyboardBeginFrame = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue()
        let keyboardEndFrame = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()

        let screenHeight = UIScreen.mainScreen().bounds.height
        let isBeginOrEnd = keyboardBeginFrame.origin.y == screenHeight || keyboardEndFrame.origin.y == screenHeight
        let heightOffset = keyboardBeginFrame.origin.y - keyboardEndFrame.origin.y - (isBeginOrEnd ? bottomLayoutGuide.length : 0)

        UIView.animateWithDuration(duration.doubleValue,
            delay: 0,
            options: UIViewAnimationOptions(rawValue: UInt(curve.integerValue << 16)),
            animations: { () in
                scrollBottomConstant.constant = scrollBottomConstant.constant + heightOffset
                self.view.layoutIfNeeded()
            },
            completion: nil
        )
    }
}

다음과 같이 사용할 수 있습니다.

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillChangeFrameNotification:", name: UIKeyboardWillChangeFrameNotification, object: nil)
}

...

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardWillChangeFrameNotification(notification: NSNotification) {
    self.keyboardWillChangeFrameNotification(notification, scrollBottomConstant: inputContainerBottom)
    // Write more to here if you want.
}

최완복 씨, 사용되는 견해는 무엇 inputContainerBottom입니까?
Nathaniel Blumer

@Nathaniel UITextField 또는 UITextView의 bottomLayout의 하단 공간 제약. ;) 내 프로젝트에서 편집했습니다. 나는 그것을 다시 게시 할 수 있습니다
Wanbok 최에게

4

개발자가 실제로 표시되기 전에 키보드 높이를 알아야하는 경우가있어서 인터페이스를 적절하게 사전 레이아웃 할 수 있습니다.

그렇다면 다음은 포괄적 인 사양입니다.

여기에 이미지 설명 입력

여기에는 모든 현재 버전의 iOS에서 기본적으로 켜져 있기 때문에 상단에 빠른 유형 표시 줄이 포함됩니다.

누군가 필요하다면 이것을 테스트하는 데 사용한 신속한 3 알림 설정은 다음과 같습니다.

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
}

func keyboardWillShow(notification: NSNotification) {
    guard let keyboardSize = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
    print("\(keyboardSize)")
}

1

신속한 단 하나의 문자열 :

let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size

UIKeyboardFrameEndUserInfoKey항상 저장 NSValue하므로 확인할 필요가 없습니다.


0

기본 키보드와 사용자 정의 ()간에 전환 할 때 표시되는 문제를 발견했습니다.UIPickerView ) 키보드 . 사용자 지정 키보드는 기본 키보드에서 전환 한 후 162가 아닌 253 높이로 표시됩니다.

이 경우에 효과가 있었던 autocorrectionType = UITextAutocorrectionTypeNo;것은 사용자 정의 키보드로 입력 필드를 설정 하는 것입니다.

이 문제는 iOS 8에서만 발생했습니다 (시뮬레이터에서만 테스트 됨). iOS 9 (시뮬레이터 또는 기기)에서는 발생하지 않습니다.


0

한 줄이 아닌 Swift에서 ...

self.keyboardDidShowObserver = NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardDidShowNotification, object: nil, queue: NSOperationQueue.mainQueue(), usingBlock: { (notification) in
        if let userInfo = notification.userInfo, let keyboardFrameValue = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue {
            let keyboardRect = keyboardFrameValue.CGRectValue()
            // keyboardRect.height gives the height of the keyboard
            // your additional code here...
        }
    })

0
[notificationCenter addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note) {

    float keyboardHeight = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;

}];
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.