我正在使用 3.2 sdk 开发 iPad 应用程序。我正在处理获取键盘大小以防止我的文本字段隐藏在它后面。
我在 Xcode 中收到警告-> UIKeyboardBoundsUserInfoKey 已弃用我应该使用什么来代替收到此警告?
我正在使用 3.2 sdk 开发 iPad 应用程序。我正在处理获取键盘大小以防止我的文本字段隐藏在它后面。
我在 Xcode 中收到警告-> UIKeyboardBoundsUserInfoKey 已弃用我应该使用什么来代替收到此警告?
我使用了以前提供的解决方案,但仍然有问题。这是我想出的:
- (void)keyboardWillShow:(NSNotification *)aNotification {
[self moveTextViewForKeyboard:aNotification up:YES];
}
- (void)keyboardWillHide:(NSNotification *)aNotification {
[self moveTextViewForKeyboard:aNotification up:NO];
}
- (void) moveTextViewForKeyboard:(NSNotification*)aNotification up: (BOOL) up{
NSDictionary* userInfo = [aNotification userInfo];
// Get animation info from userInfo
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardEndFrame;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
// Animate up or down
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
CGRect newFrame = textView.frame;
CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
newFrame.origin.y -= keyboardFrame.size.height * (up? 1 : -1);
textView.frame = newFrame;
[UIView commitAnimations];
}
从文档中UIKeyboardBoundsUserInfoKey
:
包含 CGRect 的 NSValue 对象的键,该 CGRect 在窗口坐标中标识键盘的边界矩形。该值足以获得键盘的大小。如果要获取屏幕上键盘的来源(动画之前或之后),请使用通过 UIKeyboardCenterBeginUserInfoKey 或 UIKeyboardCenterEndUserInfoKey 常量从用户信息字典中获取的值。请改用 UIKeyboardFrameBeginUserInfoKey 或 UIKeyboardFrameEndUserInfoKey 键。
Apple 建议实现这样的便利例程(可以作为类别添加来实现UIScreen
):
+ (CGRect) convertRect:(CGRect)rect toView:(UIView *)view {
UIWindow *window = [view isKindOfClass:[UIWindow class]] ? (UIWindow *) view : [view window];
return [view convertRect:[window convertRect:rect fromWindow:nil] fromView:nil];
}
恢复窗口调整的键盘框架大小属性。
我采用了不同的方法,包括检查设备方向:
CGRect _keyboardEndFrame;
[[notification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&_keyboardEndFrame];
CGFloat _keyboardHeight = ([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait || [[UIDevice currentDevice] orientation] == UIDeviceOrientationPortraitUpsideDown) ? _keyboardEndFrame.size.height : _keyboardEndFrame.size.width;
您只需使用以下代码:
//NSVale *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
//instead of Upper line we can use either next line or nextest line.
//NSValue *aValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
NSValue *aValue = [info objectForKey:UIKeyboardFrameBeginUserInfoKey];
以下代码修复了Jay 的回答中的一个问题,假设UIKeyboardWillShowNotification
键盘已经存在时不会再次触发。
UIKeyboardWillShowNotification
使用日文/中文键盘打字时,即使键盘已经存在,iOS 也会使用新的键盘框架触发额外的功能,从而导致self.textView
原始代码中的高度第二次减小。
这减少self.textView
到几乎没有。然后就不可能从这个问题中恢复过来,因为我们只希望UIKeyboardWillHideNotification
下次键盘被关闭时会出现一个。
self.textView
下面的代码不是根据原始代码中是否显示/隐藏键盘来减去/增加高度,而是计算self.textView
减去屏幕上键盘高度后的最大可能高度。
这假设self.textView
假设填充视图控制器的整个视图,并且没有其他需要可见的子视图。
- (void)resizeTextViewWithKeyboardNotification:(NSNotification*)notif {
NSDictionary* userInfo = [notif userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardFrameInWindowsCoordinates;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindowsCoordinates];
[self resizeTextViewToAccommodateKeyboardFrame:keyboardFrameInWindowsCoordinates
withAnimationDuration:animationDuration
animationCurve:animationCurve];
}
- (void)resizeTextViewToAccommodateKeyboardFrame:(CGRect)keyboardFrameInWindowsCoordinates
withAnimationDuration:(NSTimeInterval)duration
animationCurve:(UIViewAnimationCurve)curve
{
CGRect fullFrame = self.view.frame;
CGRect keyboardFrameInViewCoordinates =
[self.view convertRect:keyboardFrameInWindowsCoordinates fromView:nil];
// Frame of the keyboard that intersects with the view. When keyboard is
// dismissed, the keyboard frame still has width/height, although the origin
// keeps the keyboard out of the screen.
CGRect keyboardFrameVisibleOnScreen =
CGRectIntersection(fullFrame, keyboardFrameInViewCoordinates);
// Max frame availble for text view. Assign it to the full frame first
CGRect newTextViewFrame = fullFrame;
// Deduct the the height of any keyboard that's visible on screen from
// the height of the text view
newTextViewFrame.size.height -= keyboardFrameVisibleOnScreen.size.height;
if (duration)
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
}
// Adjust the size of the text view to the new one
self.textView.frame = newTextViewFrame;
if (duration)
{
[UIView commitAnimations];
}
}
另外,不要忘记在 viewDidLoad 中注册键盘通知:
- (void)viewDidLoad
{
[super viewDidLoad];
NSNotificationCenter* notifCenter = [NSNotificationCenter defaultCenter];
[notifCenter addObserver:self selector:@selector(resizeTextViewWithKeyboardNotification:) name:UIKeyboardWillShowNotification object:nil];
[notifCenter addObserver:self selector:@selector(resizeTextViewWithKeyboardNotification:) name:UIKeyboardWillHideNotification object:nil];
}
将 textView 调整大小代码分为两部分 (resizeTextViewWithKeyboardNotification:
和resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve:
) 的原因是为了解决另一个问题,当键盘通过从一个视图控制器推送到另一个视图控制器时仍然存在(请参阅当 iOS 键盘在控制器之间停留时如何检测它?) .
由于在推送视图控制器之前键盘已经存在,因此 iOS 不会生成额外的键盘通知,因此无法textView
根据这些键盘通知调整大小。
因此,上述调整大小的代码(以及原始代码)仅在加载视图后self.textView
显示键盘时才有效。
我的解决方案是创建一个存储最后一个键盘坐标的单例,然后在- viewDidAppear:
viewController 上调用:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Resize the view if there's any keyboard presence before this
// Only call in viewDidAppear as we are unable to convertRect properly
// before view is shown
[self resizeViewToAccommodateKeyboardFrame:[[UASKeyboard sharedKeyboard] keyboardFrame]
withAnimationDuration:0
animationCurve:0];
}
UASKeyboard
是我的单身人士。理想情况下,我们应该将其称为 in - viewWillAppear:
,但是根据我的经验(至少在 iOS 6 上),convertRect:fromView:
我们需要使用的方法resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve:
在视图完全可见之前无法正确地将键盘框架转换为视图坐标。
只需使用UIKeyboardFrameBeginUserInfoKey
orUIKeyboardFrameEndUserInfoKey
键代替UIKeyboardBoundsUserInfoKey
@Jason,除了一点之外,如果可以的话,您可以编写代码。
目前,您实际上并没有为任何东西设置动画,视图将简单地“弹出”到它的新 size.height。
您必须指定一个动画状态。动画是一种(从状态)->(到状态)的东西。
幸运的是,有一种非常方便的方法可以将视图的当前状态指定为(来自状态)。
[UIView setAnimationBeginsFromCurrentState:YES];
如果您在 beginAnimations:context: 之后添加该行,您的代码将完美运行。
- (CGSize)keyboardSize:(NSNotification *)aNotification {
NSDictionary *info = [aNotification userInfo];
NSValue *beginValue = [info objectForKey:UIKeyboardFrameBeginUserInfoKey];
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
CGSize keyboardSize;
if ([UIKeyboardDidShowNotification isEqualToString:[aNotification name]]) {
_screenOrientation = orientation;
if (UIDeviceOrientationIsPortrait(orientation)) {
keyboardSize = [beginValue CGRectValue].size;
} else {
keyboardSize.height = [beginValue CGRectValue].size.width;
keyboardSize.width = [beginValue CGRectValue].size.height;
}
} else if ([UIKeyboardDidHideNotification isEqualToString:[aNotification name]]) {
// We didn't rotate
if (_screenOrientation == orientation) {
if (UIDeviceOrientationIsPortrait(orientation)) {
keyboardSize = [beginValue CGRectValue].size;
} else {
keyboardSize.height = [beginValue CGRectValue].size.width;
keyboardSize.width = [beginValue CGRectValue].size.height;
}
// We rotated
} else if (UIDeviceOrientationIsPortrait(orientation)) {
keyboardSize.height = [beginValue CGRectValue].size.width;
keyboardSize.width = [beginValue CGRectValue].size.height;
} else {
keyboardSize = [beginValue CGRectValue].size;
}
}
return keyboardSize;
}
它是这样工作的
这是保存按钮底部的约束
@IBOutlet weak var saveBtnBottom: NSLayoutConstraint!
@IBOutlet weak var nameText: UITextField!
内部 viewDidLoad
NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
nameText.delegate = self
这是我们需要的功能
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
nameText.resignFirstResponder()
return true
}
@objc func keyBoardWillShow(notification: Notification){
if let userInfo = notification.userInfo as? Dictionary<String, AnyObject>{
let frame = userInfo[UIResponder.keyboardFrameEndUserInfoKey]
let keyBoardRect = frame?.cgRectValue
if let keyBoardHeight = keyBoardRect?.height {
self.saveBtnBottom.constant = keyBoardHeight
UIView.animate(withDuration: 0.5, animations: {
self.view.layoutIfNeeded()
})
}
}
}
@objc func keyBoardWillHide(notification: Notification){
self.saveBtnBottom.constant = 30.0
UIView.animate(withDuration: 0.5, animations: {
self.view.layoutIfNeeded()
})
}