Ответ 1
Использование
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
Я использовал этот код для определения размера клавиатуры:
- (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 может вызываться несколько раз с помощью пользовательских реализаций клавиатуры:
Чтобы правильно обрабатывать эти сценарии в одной строке кода, вам необходимо:
Зарегистрируйте наблюдателей против уведомлений 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. Это значение можно использовать для анимации ваших изменений с той же скоростью, что и отображаемая клавиатура.
Внедрить keyboardWideHide в reset _currentKeyboardHeight и реагировать на отклонение клавиатуры:
- (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:
Преобразование UIKeyboardFrameEndUserInfoKey
Это показывает вам, как использовать функцию convertRect
, чтобы преобразовать размер клавиатуры в нечто полезное, но на экране.
NSDictionary* d = [notification userInfo];
CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];
r = [myView convertRect:r fromView:nil];
Раньше у меня было приложение для iPad, в котором UIKeyboardFrameEndUserInfoKey
< < не использовалось, и он работал нормально.
Но с iOS 8 он больше не работал должным образом. Внезапно он сообщил, что моя клавиатура, работающая на iPad в ландшафтном режиме, была на высоте 1024 пикселей.
Итак, теперь с iOS 8 вам необходимо использовать эту функцию convertRect
.
Аналогично решению dgangsta, написанному в Swift 2.0:
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.
Вот установка уведомлений быстрой настройки 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)")
}
Я заметил проблему, возникающую при переключении между клавиатурой по умолчанию и пользовательской клавиатурой (UIPickerView
) - пользовательская клавиатура будет показывать высоту 253 вместо 162 после переключения с клавиатуры по умолчанию.
В этом случае работала настройка autocorrectionType = UITextAutocorrectionTypeNo;
для поля ввода с пользовательской клавиатурой.
Проблема произошла только в iOS 8 (только на симуляторе). Это не происходит в iOS 9 (симулятор или устройство).
Только одна строка для быстрого:
let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size
UIKeyboardFrameEndUserInfoKey
всегда хранит NSValue
, поэтому нет необходимости его проверять.
В 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...
}
})
[notificationCenter addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note) {
float keyboardHeight = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
}];