私はこのコードを使用してキーボードのサイズを決定していました:
- (void)keyboardWillChange:(NSNotification *)notification {
NSDictionary* keyboardInfo = [notification userInfo];
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
}
これをシミュレーターで実行しています。
問題は、iOS 8以降では正しい値が得られないことです。キーボードの提案が有効な場合、またはそれらを押し下げると、異なる(正しくない)値が得られます。
キーボード候補を含むキーボードの正確なサイズを取得するにはどうすればよいですか?
つかいます
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
IOSにカスタムキーボードを導入すると、この問題は少し複雑になります。
つまり、UIKeyboardWillShowNotificationは、カスタムキーボードの実装によって複数回呼び出されることがあります。
これらのシナリオを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;
}
このStackOverflowの記事に出くわすまで、この問題もありました。
IKeyboardFrameEndUserInfoKeyを変換
これは、convertRect
関数を使用して、キーボードのサイズを画面の向きに合わせて使用可能なサイズに変換する方法を示しています。
NSDictionary* d = [notification userInfo];
CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];
r = [myView convertRect:r fromView:nil];
以前は、UIKeyboardFrameEndUserInfoKey
を使用するiPadアプリがありましたが、did n'tはconvertRect
を使用し、正常に機能しました。
しかし、iOS 8では、正常に動作しなくなりました。突然、iPadを横向きモードで実行しているキーボードが1024ピクセルの高さであると報告されました。
したがって、iOS 8では、このconvertRect
関数を使用することが不可欠です。
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
}
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.
}
開発者が実際に表示される前にキーボードの高さを知る必要があり、適切にインターフェースを事前にレイアウトできる場合があります。
その場合、包括的な仕様は次のとおりです。
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)")
}
[notificationCenter addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note) {
float keyboardHeight = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
}];
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...
}
})
Swiftには1つの文字列のみ:
let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size
UIKeyboardFrameEndUserInfoKey
は常にNSValue
を保存するため、チェックする必要はありません。
デフォルトのキーボードとカスタム(UIPickerView
)キーボードを切り替えると、デフォルトのキーボードから切り替えた後、カスタムキーボードが162ではなく253の高さを表示するという問題に気付きました。
この場合に機能したのは、カスタムキーボードの入力フィールドにautocorrectionType = UITextAutocorrectionTypeNo;
を設定することでした。
この問題はiOS 8でのみ発生しました(シミュレーターのみでテスト済み)。 iOS 9(シミュレーターまたはデバイス)では発生しません。