51

我正在使用 3.2 sdk 开发 iPad 应用程序。我正在处理获取键盘大小以防止我的文本字段隐藏在它后面。

我在 Xcode 中收到警告-> UIKeyboardBoundsUserInfoKey 已弃用我应该使用什么来代替收到此警告?

4

9 回答 9

87

我使用了以前提供的解决方案,但仍然有问题。这是我想出的:

    - (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];
}
于 2010-05-29T08:21:25.010 回答
57

文档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;
于 2010-05-11T00:38:09.317 回答
9

您只需使用以下代码:

//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];
于 2010-12-02T10:48:33.240 回答
3

以下代码修复了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:在视图完全可见之前无法正确地将键盘框架转换为视图坐标。

于 2012-10-18T11:21:02.880 回答
2

只需使用UIKeyboardFrameBeginUserInfoKeyorUIKeyboardFrameEndUserInfoKey键代替UIKeyboardBoundsUserInfoKey

于 2012-10-05T05:26:49.260 回答
1

@Jason,除了一点之外,如果可以的话,您可以编写代码。

目前,您实际上并没有为任何东西设置动画,视图将简单地“弹出”到它的新 size.height。

您必须指定一个动画状态。动画是一种(从状态)->(到状态)的东西。

幸运的是,有一种非常方便的方法可以将视图的当前状态指定为(来自状态)。

[UIView setAnimationBeginsFromCurrentState:YES];

如果您在 beginAnimations:context: 之后添加该行,您的代码将完美运行。

于 2010-06-22T09:39:14.347 回答
1
- (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;
}
于 2011-03-07T10:32:02.843 回答
0

这是一个很好的细节 http://i-phone-dev.blogspot.com/2012/01/different-way-to-show-keyboard-and.html

于 2012-01-18T11:47:22.343 回答
0

它是这样工作的

这是保存按钮底部的约束

@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()
    })
}
于 2019-02-15T13:38:41.813 回答