【问题标题】:What is the animation speed of the keyboard appearing in iOS8?iOS8中出现键盘的动画速度是多少?
【发布时间】:2014-09-15 09:09:06
【问题描述】:

下面是一个textField和toolBar在键盘出现时向上移动的动画。

    baseConstraint.constant = 211
    self.view.setNeedsUpdateConstraints()

    UIView.animateWithDuration(0.30, animations: {
        self.view.layoutIfNeeded()
        })

它很接近,但并不完全相同。你会如何修改上面的动画?

编辑:

这是使用下面答案的最终代码!

   func keyboardWillShow(aNotification: NSNotification)    {

        let duration = aNotification.userInfo.objectForKey(UIKeyboardAnimationDurationUserInfoKey) as Double
        let curve = aNotification.userInfo.objectForKey(UIKeyboardAnimationCurveUserInfoKey) as UInt

        self.view.setNeedsLayout()
        baseConstraint.constant = 211
        self.view.setNeedsUpdateConstraints()

        UIView.animateWithDuration(duration, delay: 0, options: UIViewAnimationOptions.fromMask(curve), animations: {
        self.view.layoutIfNeeded()
        }, completion: {
        (value: Bool) in println()
        })
}

【问题讨论】:

    标签: ios objective-c swift ios8


    【解决方案1】:

    您可以从keyboardWillShow:notifications上的userInfo字典中获取动画时长和动画曲线。

    首先注册通知

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

    然后从通知 userInfo 键中获取值。

    - (void)keyboardWillShow:(NSNotification*)notification {
        NSNumber *duration = [notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
        NSNumber *curve = [notification.userInfo objectForKey: UIKeyboardAnimationCurveUserInfoKey];
    
       // Do stuff with these values.
    }
    

    这些键还有很多,您也可以从 UIKeyboardWillDismiss 通知中获取它们。

    这个功能一直可用到 iOS 3.0 :D

    这是文档:

    https://developer.apple.com/library/ios/documentation/uikit/reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html#//apple_ref/doc/constant_group/Keyboard_Notification_User_Info_Keys

    斯威夫特版本

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
    
    @objc func keyboardWillShow(_ notification: Notification) {
        let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey]
        let curve = notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey]
    }
    

    【讨论】:

    • 您可能还想提到这在 iOS 7(及更早版本)中也有效。 :) 我不确定这是否清楚......
    • 刚刚添加!谢谢:)
    • 确保您注册的通知是 UIKeyboardWillShowNotification,而不是 UIKeyboardDidShowNotification
    • 我尝试了这些,但动画仍然无法正常工作。我正在使用 self.view.frame = CGRectOffset(self.view.frame, 0, motion) 而不是 self.view.setNeedsLayout() self.view.setNeedsUpdateConstraints() 这有关系吗?
    • Doesn't work in Swift 2 返回以下错误:Value of type '[NSObject : AnyObject]?'没有成员“objectForKey”。解决方法是 (aNotification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as?NSTimeInterval)
    【解决方案2】:

    具有可变持续时间的答案是正确的,并且适用于 iOS 3 到 8,但是对于新版本的 Swift,答案的代码不再有效。 也许这是我的错误,但我必须写:

    let duration = aNotification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as Double
    let curve = aNotification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as UInt
    
    self.view.setNeedsLayout()
    //baseConstraint.constant = 211
    self.view.setNeedsUpdateConstraints()
    
    UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions(curve), animations: { _ in
        //self.view.layoutIfNeeded()
    }, completion: { aaa in
        //(value: Bool) in println()
    })
    

    看起来 objectForKey 不再工作了,转换更加严格。

    【讨论】:

    • 我尝试了这些,但动画仍然无法正常工作。我正在使用 self.view.frame = CGRectOffset(self.view.frame, 0, motion) 而不是 self.view.setNeedsLayout() self.view.setNeedsUpdateConstraints() 这有关系吗?
    • 我不明白你的问题在哪里,但是现在 Swift 是一个干净的代码,我这样使用它: override func keyboardWillShow(note: NSNotification) { super.keyboardWillShow(note) UIView.animateWithDuration (note.animationDuration) { // 你的改变 } }
    • 对于 Swift 2.2,我必须做两处改变:对于演员表,你是 as! 而不是 as;并使用UIViewAnimationOptions(rawValue: curve) 而不是UIViewAnimations(curve)
    【解决方案3】:

    swift3

        let duration = noti.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
        let curve = noti.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber
    
        self.view.setNeedsLayout()
    
        UIView.animate(withDuration: TimeInterval(duration), delay: 0, options: [UIViewAnimationOptions(rawValue: UInt(curve))], animations: {
          self.view.layoutIfNeeded()
        }, completion: nil)
    

    【讨论】:

    • 如何更改时长?
    【解决方案4】:

    Swift 4 更新,iOS 11+

    首先在视图的生命周期方法中注册通知:

    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
    }
    

    然后在keyBoardWillShow方法中:

    @objc func keyBoardWillShow(notification: NSNotification) {
        guard let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double else {return}
        print(duration) // you got animation's duration safely unwraped as a double
    }
    

    最后别忘了在deinit方法中移除观察者:

    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    

    【讨论】:

      【解决方案5】:

      首先,选择的答案是正确的方法。

      这里可以提供更多的是动画的真正含义。如果您在 UIViewAnimation 块中打印所有 CAAnimation,当将动画曲线设置为键盘通知中提供的曲线时,您会发现 这是一个 CASpringAnimation。持续时间为0.5,其他参数为:

      let ani = CASpringAnimation(keyPath: someKey)
      ani.damping = 500
      ani.stiffness = 1000
      ani.mass = 3
      ani.duration = 0.5
      

      以上代码可以精确再现动画。

      一旦动画曲线设置为键盘一,UIView动画将忽略参数中的持续时间。 (如果你真的想改变持续时间,调整mass的值。)

      【讨论】:

      • 你是从现有动画中查询到这个的吗?
      【解决方案6】:

      Swift 5 解决方案

      let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
      let curve = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as! UInt
      
      UIView.animate(
             withDuration: duration,
             delay: 0.0,
             options: UIView.AnimationOptions(rawValue: curve),
             animations: {
                 self.view.layoutIfNeeded()
             }
      )
      

      【讨论】:

        【解决方案7】:

        // 首先在你的类 UITextFieldDelegate 中声明委托

        //放置在视图控制器的顶部

         // ****************** Keyboard Animation ***************
        var animateDistance = CGFloat()
        struct MoveKeyboard {
            static let KEYBOARD_ANIMATION_DURATION : CGFloat = 0.3
            static let MINIMUM_SCROLL_FRACTION : CGFloat = 0.2;
            static let MAXIMUM_SCROLL_FRACTION : CGFloat = 0.8;
            static let PORTRAIT_KEYBOARD_HEIGHT : CGFloat = 216;
            static let LANDSCAPE_KEYBOARD_HEIGHT : CGFloat = 162;
        }
        //
        

        //在你的类中复制和破坏文本字段的委托方法

        func textFieldDidBeginEditing(textField: UITextField) {
            let textFieldRect : CGRect = self.view.window!.convertRect(textField.bounds, fromView: textField)
            let viewRect : CGRect = self.view.window!.convertRect(self.view.bounds, fromView: self.view)
            let midline : CGFloat = textFieldRect.origin.y + 0.5 * textFieldRect.size.height
            let numerator : CGFloat = midline - viewRect.origin.y - MoveKeyboard.MINIMUM_SCROLL_FRACTION * viewRect.size.height
            let denominator : CGFloat = (MoveKeyboard.MAXIMUM_SCROLL_FRACTION - MoveKeyboard.MINIMUM_SCROLL_FRACTION) * viewRect.size.height
            var heightFraction : CGFloat = numerator / denominator
        
            if heightFraction > 1.0 {
                heightFraction = 1.0
            }
            let orientation : UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation
            if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown) {
                animateDistance = floor(MoveKeyboard.PORTRAIT_KEYBOARD_HEIGHT * heightFraction)
            } else {
                animateDistance = floor(MoveKeyboard.LANDSCAPE_KEYBOARD_HEIGHT * heightFraction)
            }
        
            var viewFrame : CGRect = self.view.frame
            viewFrame.origin.y -= animateDistance
            UIView.beginAnimations(nil, context: nil)
            UIView.setAnimationBeginsFromCurrentState(true)
            UIView.setAnimationDuration(NSTimeInterval(MoveKeyboard.KEYBOARD_ANIMATION_DURATION))
            self.view.frame = viewFrame
            UIView.commitAnimations()
        }
        func textFieldDidEndEditing(textField: UITextField) {
            var viewFrame : CGRect = self.view.frame
            viewFrame.origin.y += animateDistance
        
            UIView.beginAnimations(nil, context: nil)
            UIView.setAnimationBeginsFromCurrentState(true)
        
            UIView.setAnimationDuration(NSTimeInterval(MoveKeyboard.KEYBOARD_ANIMATION_DURATION))
        
            self.view.frame = viewFrame
        
            UIView.commitAnimations()
        
        }
        func textFieldShouldReturn(textField: UITextField) -> Bool {
            textField.resignFirstResponder()
            return true
        }
        

        【讨论】:

          【解决方案8】:

          Swift 5 的正确解决方案

          NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
          

          然后

          @objc func keyboardWillChange(notification: NSNotification) {
          
              guard let userInfo = notification.userInfo else { return }
          
              let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as! Double
              let curve = userInfo[UIKeyboardAnimationCurveUserInfoKey] as! UInt
              let targetFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
          
              self.bottomConstraint.constant = UIScreen.main.bounds.height - targetFrame.origin.y
          
              UIView.animate(withDuration: duration) {
                  self.view.layoutIfNeeded()
              }
          }
          

          【讨论】:

            【解决方案9】:

            我想指出在解决这个问题时让我感到困惑的一些事情。由于新的“quickype”视图及其显示/隐藏功能(仅限 iOS8),我需要键盘的尺寸。这就是我最终解决它的方式:

            - (void)keyboardWillChangeFrame:(NSNotification *)notification {
                NSValue *value = notification.userInfo[UIKeyboardFrameEndUserInfoKey];
                self.keyboardFrame = [value CGRectValue];
            
                NSTimeInterval duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
            
                [UIView animateWithDuration:duration animations:^{
                //ANIMATE VALUES HERE
            }];
            

            }

            【讨论】:

            • 注意:在这种情况下,您会在“quicktype”视图折叠/展开、曲线和持续时间 = 0 时收到 KeyboardWillShow 事件。与 UIKeyboardFrameEndUserInfoKey 键一起传递的大小是正确的。
            【解决方案10】:
            //--------------------------------------------------------------
            // MARK: -
            // MARK: - UITextFieldDelegate
            //--------------------------------------------------------------
            //To trigger event when user types in fields
            //right click in IB and choose EditingChanged >> textField_EditingChanged
            //NOTE IF KEYBOARD NOT SHOWING IN SIMULATOR and no view appearing ITS TURNED OFF BY DEFAULT SO YOU CAN TYPE WITH YOUR MAC KEYBOARD - HIT CMD+K or Simulator > Menu > Toggle Software Keyboard...
            
            @IBAction func textField_EditingChanged(textField: UITextField) {
                //if more than one search
                if(textField == self.textFieldAddSearch){
                    appDelegate.log.error("self.textFieldAddSearch: '\(self.textFieldAddSearch.text)'")
                    if textField.text == ""{
            
                    }else{
                        callJSONWebservices(textField.text)
                    }
                }else{
                    appDelegate.log.error("textFieldDidBeginEditing: unhandled textfield")
                }
            }
            
            //TWO WAYS TO HIDE THE VIEW
            //textFieldShouldReturn
            //buttonCancel_Action
            
            //USER HIT RETURN BUTTON ON keyboard >> resignFirstResponder >> triggers  keyboardWillHide
            func textFieldShouldReturn(textField: UITextField)-> Bool{
            
                //triggers keyboardWillHide: which also fades out view
                self.textFieldAddSearch.resignFirstResponder()
            
                return false
            }
            
            //--------------------------------------------------------------
            // MARK: -
            // MARK: - KEYBORAD
            //--------------------------------------------------------------
            private func subscribeToKeyboardNotifications() {
            
                NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
                NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
            }
            
            private func unsubscribeFromKeyboardNotifications() {
            
                NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
                NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
            }
            func keyboardWillShow(notification: NSNotification) {
            
                if let userInfo = notification.userInfo {
                    if let heightKeyboard = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().height {
                        if let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue {
            
                            self.viewAddNewSearchResults.alpha = 0.0
                            self.viewAddNewSearchResults.hidden = false
                            if let curve = userInfo[UIKeyboardAnimationDurationUserInfoKey]?.integerValue {
            
                                appDelegate.log.info("keyboardWillShow: duration:\(duration)")
            
                                UIView.animateWithDuration(duration, delay:0.0, options: .CurveEaseInOut,
                                    animations: {
                                        //self.view.frame = CGRectMake(0, 0, Geo.width(), Geo.height() - height)
                                        self.viewAddNewSearchResults_BottomConstraint.constant = heightKeyboard;
                                        self.viewAddNewSearchResults.alpha = 1.0
                                    },
                                    completion: nil)
                            }
                        }
                    }
                }
            
            }
            
            func keyboardWillHide(notification: NSNotification) {
            
                if let userInfo = notification.userInfo {
                    if let heightKeyboard = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().height {
                        if let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue {
                            if let curve = userInfo[UIKeyboardAnimationDurationUserInfoKey]?.integerValue {
            
                                appDelegate.log.info("keyboardWillHide: duration:\(duration)")
            
                                UIView.animateWithDuration(duration, delay:0.0, options: .CurveEaseInOut,
                                    animations: {
                                        self.viewAddNewSearchResults_BottomConstraint.constant = 0;
                                        self.viewAddNewSearchResults.alpha = 0.0
                                    },
                                    completion: nil)
                            }
                        }
                    }
                }
            }
            
            //Add button shows search result panel below search text fields
            //just set focus in the textField
            //then the keyboardWillShow will fade in the view and resize it to fit above the keyboard
            //and match fade in duration to animation of keyboard moving up
            @IBAction func buttonAdd_Action(sender: AnyObject) {
            
                //triggers keyboardWillHide: which also fades out view
                self.textFieldAddSearch.resignFirstResponder()
            }
            
            //TWO WAYS TO HIDE THE VIEW
            //textFieldShouldReturn
            //buttonCancel_Action
            
            //Cancel on the search results - just resignFirstResponder >> triggers keyboardWillHide: which also fades out view
            @IBAction func buttonCancel_Action(sender: AnyObject) {
                //triggers keyboardWillHide: which also fades out view
                self.textFieldAddSearch.resignFirstResponder()
            }
            

            【讨论】:

              【解决方案11】:

              斯威夫特 4

               NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
              
               func keyboardWillShow(notification: NSNotification) {
                    let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]
                    print("duration",duration)
               }
              

              【讨论】:

                猜你喜欢
                • 2010-11-28
                • 2019-02-01
                • 1970-01-01
                • 1970-01-01
                • 2014-07-28
                • 2012-07-02
                • 2011-05-11
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多