Keyboard Animation Curve as Int
Asked Answered
M

3

9

I am trying to get the UIAnimationCurve of the keyboard, if it exists. The code I am using is below:

if let kbCurve = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? Int{
                animateCurve = UIViewAnimationCurve.
            }

However, animateCurve, being a UIViewAnimationCurve, cannot be converted from an Int. How do I get the curve this way?

If I treat them as numbers, not UIViewAnimationCurve enums, the below errors when attempting to animate:

//Animated done button with keyboard
        origDoneFrame = btnDone.frame
        btnDone.hidden = false
        UIView.animateWithDuration(
            animateDuration,
            delay: Numbers.ANIMATE_DELAY,
            options: nil,
            animations: {
                UIView.setAnimationCurve(animateCurve)
                self.btnDone.frame = CGRectMake(self.btnDone.frame.origin.x + kbHeight, self.btnDone.frame.origin.y, self.btnDone.frame.size.width, self.btnDone.frame.size.height)
                return Void()
            },
            completion: {finished in
                return Void()
            }
        )

Is there a way to set the curve using an int?

Attempted int curve with:

UIView.animateWithDuration(
            animateDuration,
            delay: Numbers.ANIMATE_DELAY,
            options: UIViewAnimationOptions(animateCurve << 16),
            animations: {
                self.btnDone.frame = CGRectMake(self.btnDone.frame.origin.x + kbHeight, self.btnDone.frame.origin.y, self.btnDone.frame.size.width, self.btnDone.frame.size.height)
                return Void()
            },
            completion: {finished in
                return Void()
            }
        )

But compile error occurs due to UIViewAnimationOptions not being correct type. If I run the assignment of UIViewAnimationOptions on it's own, I get the compiler error "Could not find an overload for 'init' that accepts the supplied arguments."

Mannered answered 14/11, 2014 at 21:23 Comment(2)
Have you tried using as? UIViewAnimationCurve instead?Rush
@IanMacDonald That does not compile. The error is something that doesn't pretain tot he actual issue (as I've noticed is often the case with XCode, but the 7 doesn't match to an enum (see nickgraef's response below)Mannered
C
20

You can get an enum value from the raw Int value with

animateCurve = UIViewAnimationCurve(rawValue: kbCurve)

However, the standard keyboard uses an animation curve value of 7, which might not match up with an enum value, so animateCurve would be nil. If this is the case, just define animateCurve as an Int and use the raw values in your code rather than the enum values.

Additionally, a quick Google search turned up this wrapper, which might be useful to you: https://gist.github.com/kristopherjohnson/13d5f18b0d56b0ea9242

Update to answer edited question:

You can use an integer animation curve value in the animation options by converting it to a UIViewAnimationOptions value:

UIViewAnimationOptions(kbCurve << 16)  // where kbCurve: UInt

Update for Swift 1.2 (XCode 6.3):

The release notes for Swift 1.2 indicate that NS_ENUM types with undocumented values can now be converted from their raw integer values without being reset to nil. So the following code will now work:

let animateCurve = UIViewAnimationCurve(rawValue: userInfo[UIKeyboardAnimationCurveUserInfoKey].integerValue)!

Update for Swift 2.2 (XCode 7.3):

if let animationCurveInt = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.unsignedIntegerValue {
  let animationCurve = UIViewAnimationOptions(rawValue: animationCurveInt<<16)
  ...
}
Chancre answered 14/11, 2014 at 21:42 Comment(8)
You are correct. 7 does not match up with an enum. However, when I attempt to do the above (see edited post), it errors on UIView.setAnimationCurve.Mannered
@Mannered I've updated my answer to show how you can use the 7 value as an animation curve.Chancre
I've tried your solution, but got a compiler error. I've adjusted the post above.Mannered
@Mannered You need to bit shift kbCurve (an Int), not animateCurve (an enum value)Chancre
animateCurve in this case is an Int. I should have clarified that. I used UIViewAnimationCurve.EaseInOut.rawValue to get my default Int value.Mannered
@Mannered Ah ok, animateCurve actually needs to be a UInt, not Int. My bad.Chancre
How do you do it in Swift 2?Mature
@NicolasMiari updated for Swift 2+ - I used a "if let" above but in my real code I use guard.Variegate
T
3

Swift 4 version:

if let curveValue = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uintValue {
    let curveAnimationOptions = UIViewAnimationOptions(rawValue: curveValue << 16)
    //...
}
Trinidadtrinitarian answered 7/11, 2018 at 20:12 Comment(0)
C
0

You should use an older API, non-block based one. Then you will be able to set animation curve, which you will obtain from notification object.

Compliance answered 15/11, 2014 at 0:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.