iOS:如何将UIViewAnimationCurve转换为UIViewAnimationOptions?

2020/12/10 03:21 · ios ·  · 0评论

UIKeyboardAnimationCurveUserInfoKey有一个UIViewAnimationCurve值。如何将其转换UIViewAnimationOptions为与options参数一起使用的相应+[UIView animateWithDuration:delay:options:animations:completion:]

// UIView.h

typedef enum {
    UIViewAnimationCurveEaseInOut,         // slow at beginning and end
    UIViewAnimationCurveEaseIn,            // slow at beginning
    UIViewAnimationCurveEaseOut,           // slow at end
    UIViewAnimationCurveLinear
} UIViewAnimationCurve;

// ...

enum {
    // ...
    UIViewAnimationOptionCurveEaseInOut            = 0 << 16, // default
    UIViewAnimationOptionCurveEaseIn               = 1 << 16,
    UIViewAnimationOptionCurveEaseOut              = 2 << 16,
    UIViewAnimationOptionCurveLinear               = 3 << 16,
    // ...
};
typedef NSUInteger UIViewAnimationOptions;

显然,我可以使用一条switch语句创建一个简单的类别方法,如下所示:

// UIView+AnimationOptionsWithCurve.h

@interface UIView (AnimationOptionsWithCurve)
@end

// UIView+AnimationOptionsWithCurve.m

@implementation UIView (AnimationOptionsWithCurve)

+ (UIViewAnimationOptions)animationOptionsWithCurve:(UIViewAnimationCurve)curve {
    switch (curve) {
        case UIViewAnimationCurveEaseInOut:
            return UIViewAnimationOptionCurveEaseInOut;
        case UIViewAnimationCurveEaseIn:
            return UIViewAnimationOptionCurveEaseIn;
        case UIViewAnimationCurveEaseOut:
            return UIViewAnimationOptionCurveEaseOut;
        case UIViewAnimationCurveLinear:
            return UIViewAnimationOptionCurveLinear;
    }
}

@end

但是,有没有更简单/更好的方法呢?

可以说,您可以采用第一个解决方案并使之成为内联函数,以节省堆栈推送。它是如此严格的条件(常量绑定等),因此应将其编译成很小的程序集。

编辑:每个@matt,在这里,您去(Objective-C):

static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCurve curve)
{
  switch (curve) {
    case UIViewAnimationCurveEaseInOut:
        return UIViewAnimationOptionCurveEaseInOut;
    case UIViewAnimationCurveEaseIn:
        return UIViewAnimationOptionCurveEaseIn;
    case UIViewAnimationCurveEaseOut:
        return UIViewAnimationOptionCurveEaseOut;
    case UIViewAnimationCurveLinear:
        return UIViewAnimationOptionCurveLinear;
  }
}

斯威夫特3:

extension UIViewAnimationOptions {
    init(curve: UIViewAnimationCurve) {
        switch curve {
            case .easeIn:
                self = .curveEaseIn
            case .easeOut:
                self = .curveEaseOut
            case .easeInOut:
                self = .curveEaseInOut
            case .linear:
                self = .curveLinear
        }
    }
}

您建议的类别方法是执行此操作的“正确”方法-您不一定要保证这些常量保持其值。但是,通过查看它们的定义,看来您可以做到

animationOption = animationCurve << 16;

...可能会先转换为NSUInteger,然后转换为UIViewAnimationOptions,如果编译器希望对此进行抱怨。

在Swift中,您可以

extension UIViewAnimationCurve {
    func toOptions() -> UIViewAnimationOptions {
        return UIViewAnimationOptions(rawValue: UInt(rawValue << 16))
    }
}

基于开关的解决方案的一个问题是,它假定不会传递任何选项组合。但是,实践表明,在某些情况下,该假设不成立。我发现的一个实例是(至少在iOS 7上)当您获得键盘动画以对内容以及键盘的外观/动画进行动画处理时。

如果您收听keyboardWillShow:keyboardWillHide:通知,然后获得曲线,键盘将宣布它将使用,例如:

UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];

您可能会获得值7。如果将其传递到切换功能/方法中,则将无法正确转换该值,从而导致动画行为不正确。

Noah Witherspoon的答案将返回正确的值。结合两个解决方案,您可能会编写如下内容:

static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCurve curve)
{
    UIViewAnimationOptions opt = (UIViewAnimationOptions)curve;
    return opt << 16;
}

诺亚也指出,这里的警告是,如果Apple更改了两种类型不再对应的枚举,则此功能将中断。无论如何,使用它的原因是,基于开关的选项并非在您今天可能遇到的所有情况下都可以使用,尽管如此。

iOS 10以上的
Swift 5

转换UIView.AnimationCurveUIView.AnimationOptions(可能甚至不可能)的Swift替代方法是使用UIViewPropertyAnimator(iOS 10+),它比接受UIView.AnimationCurve且是更现代的动画师UIView.animate

很可能您将与之一起使用UIResponder.keyboardAnimationCurveUserInfoKey,它将返回NSNumber该密钥的文档是(Apple自己的符号,不是我的):

public class let keyboardAnimationCurveUserInfoKey: String // NSNumber of NSUInteger (UIViewAnimationCurve)

使用这种方法,我们可以消除任何猜测:

if let kbTiming = notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber, // doc says to unwrap as NSNumber
    let timing = UIView.AnimationCurve.RawValue(exactly: kbTiming), // takes an NSNumber
    let curve = UIView.AnimationCurve(rawValue: timing) { // takes a raw value
    let animator = UIViewPropertyAnimator(duration: duration, curve: curve) {
        // add animations
    }
    animator.startAnimation()
}
本文地址:http://ios.askforanswer.com/iosruhejianguiviewanimationcurvezhuanhuanweiuiviewanimationoptions.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!