50

には値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

しかし、もっと簡単で良い方法はありますか?

4

5 に答える 5

44

あなたが提案するカテゴリー法はそれを行うための「正しい」方法です—あなたは必ずしもそれらの定数がそれらの値を維持するという保証を持っているわけではありません。しかし、それらがどのように定義されているかを見ると、あなたはただできるようです

animationOption = animationCurve << 16;

...コンパイラがそれについて不平を言っていると感じた場合は、おそらくNSUIntegerにキャストしてからUIViewAnimationOptionsにキャストします。

于 2011-09-06T23:39:37.777 に答える
36

間違いなく、最初のソリューションをインライン関数にして、スタックプッシュを節約することができます。これは非常に厳密な条件付き(定数バウンドなど)であるため、非常に小さなアセンブリにコンパイルする必要があります。

編集:@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
        }
    }
}
于 2011-11-16T20:53:55.237 に答える
19

Swiftでは次のことができます

extension UIViewAnimationCurve {
    func toOptions() -> UIViewAnimationOptions {
        return UIViewAnimationOptions(rawValue: UInt(rawValue << 16))
    }
}
于 2015-03-11T10:33:27.057 に答える
11

スイッチベースのソリューションの問題は、オプションの組み合わせが渡されないことを前提としていることです。ただし、実際には、前提が当てはまらない状況が存在する可能性があります。私が見つけた1つの例は、(少なくともiOS 7では)キーボードのアニメーションを取得して、キーボードの外観/非表示とともにコンテンツをアニメーション化する場合です。

keyboardWillShow:またはkeyboardWillHide:通知を聞いてから、キーボードが使用することをアナウンスする曲線を取得すると、次のようになります。

UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];

値7を取得する可能性があります。これをswitch関数/メソッドに渡すと、その値の正しい変換が得られず、アニメーションの動作が正しくなくなります。

ノアウィザースプーンの答えは正しい値を返します。2つのソリューションを組み合わせると、次のようになります。

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

ここでの注意点は、Noahも指摘しているように、Appleが2つのタイプが対応しなくなった列挙を変更すると、この関数が機能しなくなることです。とにかくそれを使用する理由は、スイッチベースのオプションが今日遭遇する可能性のあるすべての状況で機能するとは限らないためですが、これは機能します。

于 2013-11-25T09:52:17.627 に答える
5

iOS 10+
Swift 5

に変換UIView.AnimationCurveする代わりのSwiftは、 (iOS 10以降)UIView.AnimationOptionsを使用することです。これは、を受け入れ、より最新のアニメーターです。UIViewPropertyAnimatorUIView.AnimationCurveUIView.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()
}
于 2020-06-18T16:36:53.113 に答える