在 iOS8 中无法获得正确的键盘高度值
Posted
技术标签:
【中文标题】在 iOS8 中无法获得正确的键盘高度值【英文标题】:can't get correct value of keyboard height in iOS8 【发布时间】:2014-11-10 13:39:40 【问题描述】:我使用这段代码来确定键盘的大小:
- (void)keyboardWillChange:(NSNotification *)notification
NSDictionary* keyboardInfo = [notification userInfo];
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
我正在模拟器中运行它。
问题是因为 ios 8 这不会给出正确的值,如果键盘建议是向上的或者如果我按下它们我会得到不同的(不正确的)值。
如何获得包括键盘建议在内的键盘的确切尺寸?
【问题讨论】:
将keyboardFrameBeginRect
转换为本地坐标可能会有所帮助。
@rmaddy 没关系,我只需要身高。
这可能是错误的,具体取决于方向。尽管在 iOS 8 下这可能不再是问题。但请尝试一下,看看它是否有所作为。
@rmaddy 我试过了,可惜没用
【参考方案1】:
使用
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
【讨论】:
很好的答案。谢谢。您是如何发现应该使用该密钥的? @souvickcse CGRect keyboardFrame = [keyboardFrameBegin CGRectValue]; 对我不起作用,键盘还是 258,太高了 在iPhone横屏模式下,我发现在iOS 10(普通键盘)上必须使用UIKeyboardFrameBeginUserInfoKey
,否则原点报错。
今天吸取了教训。 UIKeyboardFrameEndUserInfoKey 和 UIKeyboardFrameBeginUserInfoKey 有很大区别。谢谢@souvickcse【参考方案2】:
随着 iOS 中自定义键盘的引入,这个问题变得有点复杂。
简而言之,UIKeyboardWillShowNotification 可以被自定义键盘实现多次调用:
-
Apple 系统键盘打开时(纵向)
UIKeyboardWillShowNotification 的键盘高度为 224
Swype 键盘 打开时(纵向):
UIKeyboardWillShowNotification 以 0 的键盘高度发送
UIKeyboardWillShowNotification 以 216 的键盘高度发送
UIKeyboardWillShowNotification 的键盘高度为 256
SwiftKey 键盘 打开时(纵向):
UIKeyboardWillShowNotification 以 0 的键盘高度发送
UIKeyboardWillShowNotification 以 216 的键盘高度发送
UIKeyboardWillShowNotification 的键盘高度为 259
为了在一个代码行中正确处理这些场景,您需要:
针对 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 键入的值。此值可用于以与显示键盘相同的速度为您的更改设置动画。
实现 keyboardWillHide 以重置 _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;
【讨论】:
dgangsta,你的研究很有趣,但问题的问题只是获取 FrameBegin 而不是 FrameEnd 属性。根据您的回答,您是否考虑过使用 UIViewAnimationOptionBeginFromCurrentState 标志来查看动画方法而不是增量? SwiftKey(v 1.2.3) 高度为 259,我在 iOS8.1.3 的 iPhone6+ 中得到 271。 它仍然是一个有效的解决方案吗?使用 SwiftKey 时,我得到的高度是 44 而不是 259。 疯了,这对我有帮助,但我需要它已经显示后的键盘高度,所以我观察了 keyboardDidShow: 。为什么这些自定义键盘会触发 3 个通知,而 Apple 只会触发一个?似乎不一致。 如果您像我一样在横向模式下遇到 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)
【参考方案3】:
我也遇到过这个问题,直到我看到这篇 *** 文章:
Convert 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 提供了正确的结果。【参考方案4】:类似dgangsta's 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
【讨论】:
显示/隐藏 quickType 以及笑脸时出现问题 这是酱汁。 Swift 2.3 中的细微差别,但它是编译器的自动完成建议,所以没有问题。【参考方案5】:我为UIViewController
制作extension
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 UITextField 或 UITextView 的底部空间限制来自 bottomLayout。 ;) 我在我的项目中编辑了它。我会转发的【参考方案6】:
我注意到在默认键盘和自定义 (UIPickerView
) 键盘之间切换时显示的问题 - 从默认键盘切换后,自定义键盘将显示 253 高度而不是 162。
在这种情况下起作用的是使用自定义键盘为输入字段设置autocorrectionType = UITextAutocorrectionTypeNo;
。
该问题仅在 iOS 8 中出现(仅在模拟器上测试)。它不会出现在 iOS 9(模拟器或设备)中。
【讨论】:
【参考方案7】:swift只有一个字符串:
let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size
UIKeyboardFrameEndUserInfoKey
始终存储NSValue
,因此无需检查。
【讨论】:
【参考方案8】:在 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...
)
【讨论】:
【参考方案9】:[notificationCenter addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note)
float keyboardHeight = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
];
【讨论】:
【参考方案10】:有时,开发人员需要在键盘实际显示之前知道它的高度,从而允许他们对界面进行适当的预布局。
如果是这样,这里有一个包容性规范:
这包括顶部的快速输入栏,因为它在所有当前版本的 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)")
【讨论】:
以上是关于在 iOS8 中无法获得正确的键盘高度值的主要内容,如果未能解决你的问题,请参考以下文章
iOS 8 自定义键盘:更改高度而不发出警告“无法同时满足约束...”