web-dev-qa-db-ja.com

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

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

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

}

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

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

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

81
Eli Braginskiy

つかいます

NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
95
souvickcse

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

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

  1. Appleシステムキーボードを開いたとき(縦向き)
    • UIKeyboardWillShowNotificationは、キーボードの高さ224で送信されます
  2. Swype keyboardを開いたとき(縦向き):
    • UIKeyboardWillShowNotificationは、キーボードの高さで送信されます
    • UIKeyboardWillShowNotificationは、キーボードの高さ216で送信されます
    • UIKeyboardWillShowNotificationは、キーボードの高さ256で送信されます
  3. SwiftKey keyboardを開いたとき(縦向き):
    • UIKeyboardWillShowNotificationは、キーボードの高さで送信されます
    • 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;
}

注:ビューのオフセットをアニメーション化することもできます。 infoディクショナリには、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;
}
120
dgangsta

このStackOverflowの記事に出くわすまで、この問題もありました。

IKeyboardFrameEndUserInfoKeyを変換

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

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

以前は、UIKeyboardFrameEndUserInfoKeyを使用するiPadアプリがありましたが、did n'tconvertRectを使用し、正常に機能しました。

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

したがって、iOS 8では、このconvertRect関数を使用することが不可欠です。

18
Mike Gledhill

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

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.
}
5
Wanbok Choi

開発者が実際に表示される前にキーボードの高さを知る必要があり、適切にインターフェースを事前にレイアウトできる場合があります。

その場合、包括的な仕様は次のとおりです。

enter image description here

IOSの現在のすべてのバージョンでデフォルトでオンになっているため、これには上部にクイックタイプバーが含まれます。

誰かがそれを必要とする場合、これをテストするために使用したSwift 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)")
}
4
Travis M.
[notificationCenter addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note) {

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

}];
0
Leo Cavalcante

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
Murray Sagal

Swiftには1つの文字列のみ:

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

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

0
Petr Syrov

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

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

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

0
alex-i