【问题标题】:iOS 7 - Keyboard animationiOS 7 - 键盘动画
【发布时间】:2013-09-28 05:52:15
【问题描述】:

我正在尝试了解 iPhone 5 模拟器上 iOS 7.0 中的新键盘动画。我想在键盘出现时调整UITableView 的大小,但我无法获得正确的动画细节。
当键盘出现或消失时,我正在使用来自NSNotification 对象的信息。

这是我的日志:

Move keyboard from {{0, 920}, {320, 216}} to {{0, 352}, {320, 216}}
 with duration: 0.400000
 and animation curve: 7

UIViewAnimationCurveEaseInOut = 0
UIViewAnimationCurveEaseIn = 1
UIViewAnimationCurveEaseOut = 2
UIViewAnimationCurveLinear = 3

动画曲线是未知值,怎么办?

【问题讨论】:

  • 检查这是否解决了您的问题stackoverflow.com/questions/11313951/…
  • 抱歉,我忘了写我正在使用 UIViewControllerUITableView 子视图。
  • 你期待什么动画细节?
  • @Krishnan 不是 7,我想。

标签: objective-c uitableview animation keyboard ios7


【解决方案1】:

在 iOS 7 中,键盘使用了一种新的、未记录的动画曲线。虽然有些人注意到对动画选项使用未记录的值,但我更喜欢使用以下内容:

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:[notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]];
[UIView setAnimationBeginsFromCurrentState:YES];

// work

[UIView commitAnimations];

虽然建议使用基于块的动画,但从键盘通知返回的动画曲线是 UIViewAnimationCurve,而您需要传递给基于块的动画的选项是 UIViewAnimationOptions。使用传统的 UIView 动画方法,您可以直接将值通过管道输入。最重要的是,这将使用新的未记录动画曲线(整数值 7)并使动画与键盘匹配。而且,它同样适用于 iOS 6 和 7。

【讨论】:

  • UIKeyboardWillShowNotification 上完美运行,但是当通过UIKeyboardWillHideNotification 关闭键盘时,我的 UIView 似乎与键盘不同步。
  • 使用无证动画曲线是否合法?如果你这样做,Apple 会拒绝你的应用吗?
  • 1) 这可能永远不会被 Apple 抓住,但一般来说直接使用它是个坏主意。 2)我们在这里不直接使用它。我们天真地传递了我们被赋予的价值。
  • @Piotr 我发现比在 iOS 7 中,当键盘执行关闭动画时,它使用未记录的 UIViewAnimationCurve 整数值为 6 而不是 @987654326 报告的值 7 @。这是一个 hacky 解决方案,但如果键盘正在关闭,使用 [UIView setAnimationCurve:6] 似乎可以使 UIView 动画保持同步。
  • 我花了很长时间试图让一些东西与他们的键盘一起正确制作动画,但在我找到这个答案之前它看起来从来没有正确过。谢谢!
【解决方案2】:

现在我找到了解决方案。动画从点{0, 920} 开始到{0, 352}。问题是UITableView对象以{160, 568}的大小开始,所以我在动画开始之前将UITableView的大小更改为{160, 920}

关于未知动画曲线,我只是将参数设置为animationCurve << 16,将其从视图动画曲线转换为视图动画选项。
该值不等于线性、缓入、缓出和缓入动画曲线。

这是我的代码:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(_keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

和:

- (void)keyboardWillShow:(NSNotification *)aNotification {
    NSDictionary *userInfo = aNotification.userInfo;

    //
    // Get keyboard size.

    NSValue *beginFrameValue = userInfo[UIKeyboardFrameBeginUserInfoKey];
    CGRect keyboardBeginFrame = [self.view convertRect:beginFrameValue.CGRectValue fromView:nil];

    NSValue *endFrameValue = userInfo[UIKeyboardFrameEndUserInfoKey];
    CGRect keyboardEndFrame = [self.view convertRect:endFrameValue.CGRectValue fromView:nil];

    //
    // Get keyboard animation.

    NSNumber *durationValue = userInfo[UIKeyboardAnimationDurationUserInfoKey];
    NSTimeInterval animationDuration = durationValue.doubleValue;

    NSNumber *curveValue = userInfo[UIKeyboardAnimationCurveUserInfoKey];
    UIViewAnimationCurve animationCurve = curveValue.intValue;

    //
    // Create animation.

    CGRect tableViewFrame = self.tableView.frame;
    bTableViewFrame.size.height = (keyboardBeginFrame.origin.y - tableViewFrame.origin.y);
    self.tableView.frame = tableViewFrame;

    void (^animations)() = ^() {
        CGRect tableViewFrame = self.tableView.frame;
        tableViewFrame.size.height = (keyboardEndFrame.origin.y - tableViewFrame.origin.y);
        self.tableView.frame = tableViewFrame;
    };

    //
    // Begin animation.

    [UIView animateWithDuration:animationDuration
                          delay:0.0
                        options:(animationCurve << 16)
                     animations:animations
                     completion:nil];
}

【讨论】:

  • "关于未知动画曲线,我只是将参数设置为animationCurve
  • 查看UIViewAnimationOptionCurveEaseIn的定义,例如UIView.h
  • 这样的事情令人非常沮丧。什么鬼,苹果?谢谢。
【解决方案3】:

您可以使用animateWithDuration 块并在其中设置曲线。它很干净而且工作得很好。

UIViewAnimationCurve curve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
double duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

[UIView animateWithDuration:duration
                    delay:0
                  options:UIViewAnimationOptionBeginFromCurrentState 
               animations:^{
                 [UIView setAnimationCurve:curve];
                 /* ANIMATION HERE */
                 // don't forget layoutIfNeeded if you use autolayout
               }
               completion:nil];

编码愉快!

更新

你可以使用我写的一个简单的UIViewController类https://github.com/Just-/UIViewController-KeyboardAnimation

【讨论】:

    【解决方案4】:

    请改用UIKeyboardWillChangeFrameNotification,因为一些国际键盘,如中文键盘,在使用过程中会改变高度。即使在横向模式下,此代码也可以为您提供正确的键盘高度。 (注意:下面的代码是Autolayout

    //set your observer, in a method like viewDidLoad
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
    
    - (void)keyboardWillChange:(NSNotification *)notification {
        CGRect initialRect = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
        CGFloat initialHeight = self.view.frame.size.height - [self.view convertRect:initialRect fromView:nil].origin.y;
        CGRect keyboardRect = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
        CGFloat newHeight = self.view.frame.size.height - [self.view convertRect:keyboardRect fromView:nil].origin.y;
        //set your constraints here, based on initialHeight and newHeight, which are the heights of the keyboard before & after animation.
        [self.contentView setNeedsUpdateConstraints];
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
        [UIView setAnimationCurve:[notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]];
        [UIView setAnimationBeginsFromCurrentState:YES];
        [self.contentView layoutIfNeeded];
        [UIView commitAnimations];
    }
    

    【讨论】:

    【解决方案5】:

    要使用与键盘相同的动画,您必须使用未记录的曲线选项。

    - (void)keyboardWillHide:(NSNotification *)notification {
        NSDictionary *userInfo = [notification userInfo];
    
        CGRect rect = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
        NSTimeInterval animationDuration = [[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
        NSInteger curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue] << 16;
    
        [UIView animateWithDuration:animationDuration delay:0.0 options:curve animations:^{
    
        } completion:nil];
    }
    

    我发现实际上animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion: 方法是现在在iOS7 和iOS8 中完成所有动画的新方法。您只需设置正确的持续时间、阻尼和速度,您将获得相同的效果,但您也可以更改速度/时间。

    【讨论】:

      【解决方案6】:

      在 Swift 4 中

      为键盘通知添加观察者:

      • UIKeyboardDidShowNotification
      • UIKeyboardDidHideNotification

      通过

      NSNotificationCenter.defaultCenter().addObserver(_ observer: Any, 
              selector aSelector: Selector, 
              name aName: NSNotification.Name?, 
              object anObject: Any?)
      

      并实现选择器以使用键盘动画为 UI 设置动画。 为了创建一个有效的曲线值,我们需要将 UIResponder.keyboardAnimationCurveUserInfoKey 移动

      func keyboardWillShow(_ notification: Notification!) {
          if let info = notification.userInfo {
              let keyboardSize = info[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect
              let duration = info[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double 
              let curveVal = (info[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber)?.intValue ?? 7 // default value for keyboard animation
              let options = UIView.AnimationOptions(rawValue: UInt(curveVal << 16))
              UIView.animate(withDuration: duration, delay: 0, options: options, animations: {
              // any operation to be performed
          }, completion: nil)
          }
      }
      

      【讨论】:

        【解决方案7】:

        在 iOS 13 中,您处于隐式动画中,因此只需在通知处理程序中修改您的布局,它就会以正确的持续时间和曲线进行动画处理。

        【讨论】:

          【解决方案8】:

          注册接收通知:

          [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
          

          通过动画更改视图的 frame.origin.y 来响应。

          - (void)keyboardWillShow:(NSNotification *)aNotification {
          
              NSDictionary *userInfo = aNotification.userInfo;
              NSValue *endFrameValue = userInfo[UIKeyboardFrameEndUserInfoKey];
              CGRect keyboardEndFrame = [self.view convertRect:endFrameValue.CGRectValue fromView:nil];
          
              [UIView beginAnimations:nil context:NULL];
              [UIView setAnimationDuration:[aNotification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
              [UIView setAnimationCurve:[aNotification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]];
              [UIView setAnimationBeginsFromCurrentState:YES];
          
              CGRect searchButtonFrame = self.searchButton.frame;
              searchButtonFrame.origin.y = (keyboardEndFrame.origin.y - searchButtonFrame.size.height);
              self.searchButton.frame = searchButtonFrame;
          
              [UIView commitAnimations];
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-10-30
            • 1970-01-01
            • 1970-01-01
            • 2014-12-18
            • 2011-11-24
            • 1970-01-01
            • 2014-10-01
            • 2013-10-02
            相关资源
            最近更新 更多