iOS8でキーボードの高さの正しい値を取得できません


83

私はこのコードを使用して、キーボードのサイズを決定していました。

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

}

私はこれをシミュレーターで実行しています。

問題は、iOS 8以降、これでは正しい値が得られないことです。キーボードの提案が上にある場合、または下に押すと、異なる(正しくない)値が得られます。

キーボードの提案を含め、キーボードの正確なサイズを取得するにはどうすればよいですか?


keyboardFrameBeginRectローカル座標に変換すると役立つ場合があります。
rmaddy 2014

@rmaddyそれは本当に重要ではありません、私は高さだけが必要です。
Eli Braginskiy 2014

向きによってはどちらが間違っている可能性があります。それはiOS8ではもはや問題ではないかもしれませんが、それでも試してみて、違いが生じるかどうかを確認してください。
rmaddy 2014

@rmaddy試してみましたが、残念ながら役に立ちませんでした
Eli Braginskiy 2014

回答:


98

使用する

NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];

素晴らしい答え。ありがとう。そのキーを使用する必要があることをどのようにして見つけましたか?@souvickcse
Julian Osorio

6
CGRect KeyboardFrame = [keyboardFrameBegin CGRectValue];
素晴らしい

12
私には
うまくいき

@trycatchfinallyありがとう
souvickcse

1
今日レッスンを学びました。UIKeyboardFrameEndUserInfoKeyとUIKeyboardFrameBeginUserInfoKeyには大きな違いがあります。@souvickcseありがとう
jejernig

120

iOSにカスタムキーボードが導入されると、この問題は少し複雑になります。

つまり、UIKeyboardWillShowNotificationは、カスタムキーボード実装によって複数回呼び出される可能性があります。

  1. ときは、アップルのシステムキーボードが(ポートレートで)開かれ
    • UIKeyboardWillShowNotificationは、キーボードの高さが224で送信されます
  2. Swypeキーボードを開いたとき(縦向き):
    • UIKeyboardWillShowNotificationは、キーボードの高さ0で送信されます
    • UIKeyboardWillShowNotificationは、キーボードの高さが216で送信されます
    • UIKeyboardWillShowNotificationは、キーボードの高さ256で送信されます
  3. SwiftKeyキーボードを開いたとき(縦向き):
    • UIKeyboardWillShowNotificationは、キーボードの高さ0で送信されます
    • UIKeyboardWillShowNotificationは、キーボードの高さが216で送信されます
    • UIKeyboardWillShowNotificationは、キーボードの高さが 259で

これらのシナリオを1つのコード行で適切に処理するには、次のことを行う必要があります。

UIKeyboardWillShowNotificationおよびUIKeyboardWillHideNotificationに対してオブザーバーを登録します通知ます。

[[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を。この値を使用して、表示されているキーボードと同じ速度で変更をアニメーション化できます。

_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 2015年

2
それはまだ実用的な解決策ですか?SwiftKey Iを使用する場合は、44の代わりに、259の高さを取得
KIDdAe

クレイジー、これは私を助けました、しかし私はそれがすでに表示された後にキーボードの高さが必要だったので、代わりにkeyboardDidShow:を観察します。これらのカスタムキーボードが3つの通知をトリガーするのに、Appleが1つだけトリガーするのはなぜですか?一貫性がないようです。
Liron Yahdav 2016

私のように横向きモードの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 2017年

18

このStackOverflowに出くわすまで、私もこの問題を抱えていました記事に。

UIKeyboardFrameEndUserInfoKeyを変換します

これは、このconvertRect関数を使用して、キーボードのサイズを使用可能なものに変換する方法を示していますが、画面の向きです。

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

以前、私はiPadアプリを使用してUIKeyboardFrameEndUserInfoKeyいましたが、使用していませんでしたconvertRect、問題なく動作しました。

しかし、iOS 8では、正しく機能しなくなりました。突然、iPadで横向きモードで実行されている私のキーボードのさが1024ピクセルであると報告されました。

そのため、iOS 8では、このconvertRect機能を使用することが不可欠です。


iOS8より前は、キーボードの長方形は常に縦向きの画面座標でした。横向きモードで高さと幅を手動で交換するコードを追加しましたが、iOS 8では壊れました。キーボードの縦向きがビューの向きと一致します。convertRect溶液は、iOS 7またはiOS 8の正しい結果を与える
user1055568

7

Swift2.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
}

quickTypeを表示/非表示にするときの問題、およびスマイリー
user3722523 2015年

これがソースでした。Swift 2.3にはわずかな違いがありますが、これはコンパイラからのオートコンプリートの提案であるため、問題はありません。
イーサンパーカー

5

extensionUIViewController

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.
}

Wanbok Choi、どのビューが使用されていinputContainerBottomますか?
Nathaniel Blumer 2016

@NathanielUITextFieldまたはbottomLayoutからのUITextViewの下部スペース制約。;)プロジェクトで編集しました。再投稿します
Wanbok Choi 2016

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

スイフトの文字列は1つだけです。

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

UIKeyboardFrameEndUserInfoKey常に保存NSValueするので、チェックする必要はありません。


0

デフォルトのキーボードとカスタムキーボードを切り替えるときに表示される問題に気づきました(UIPickerView)キーボードを。デフォルトのキーボードから切り替えた後、カスタムキーボードの高さは162ではなく253になります。

この場合にautocorrectionType = UITextAutocorrectionTypeNo;機能したのは、カスタムキーボードを使用した入力フィールドの設定でした。

この問題はiOS8でのみ発生しました(シミュレーターでのみテスト済み)。iOS 9(シミュレーターまたはデバイス)では発生しません。


0

Swiftでは、1行ではありません...

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.