5

// カード クラスのヘッダー ファイル

#import "OWCardView.h"

@implementation OWCardView;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.layer.contents      = (id) [UIImage imageNamed:@"4.png"].CGImage;
        self.layer.shadowColor   = [UIColor whiteColor].CGColor;
        self.layer.shadowOpacity = 0.3;
    }
    return self;
}


- (void) moveCard:(float)xPoint along:(float)yPoint
{
    CGRect someRect = CGRectMake(xPoint, yPoint, 72, 96);

    [UIView animateWithDuration: 3.5
                          delay: 0.3
                        options: UIViewAnimationCurveEaseOut
                     animations: ^{ self.frame = someRect;}
                     completion: ^(BOOL finished) { }];
}


@end


// part of the Implementation in the view controller's viewDidLoad

[...]
     CGRect myImageRect = CGRectMake(20.0f, 20.0f, 72.0f, 96.0f);

     // myCard is a property of the viewController
     self.myCard = [[OWCardView alloc] initWithFrame:myImageRect];
     [self.view addSubview:self.myCard];
     [self.myCard moveCard: 240 along: 355];     // First call
     [self.myCard moveCard: 50 along: 355];      // Second call
     [self.myCard moveCard: 50 along: 50];       // Third call
[...]

問題: viewController 内の moveCard への最後のメッセージのみが実行されます。最初と 2 番目の呼び出しは実行されません。コードの何が問題になっていますか?

3 番目のメッセージを moveCard out にコメントすると、2 番目の呼び出しが実行され、最初の呼び出しは実行されません。2 番目と 3 番目の呼び出しをコメントアウトすると、最初の呼び出しが実行されます。しかし、私は 3 つのアニメーションすべてをカードで発生させたいと考えています。

4

3 に答える 3

2

ビューをアニメーション化すると、いずれかのアニメーションの遅延がゼロでなくても、ビューに適用した以前のアニメーションはすぐにキャンセルされます。したがって、シーケンシャル アニメーションを適用する場合は、最初のアニメーションが終了した後に 2 番目のアニメーションを追加する必要があります。完了ブロックを使用して、最初のアニメーションがいつ終了するかを検出できます。

moveCard:along:ターゲット四角形のキューを維持し、アニメーションを順番に適用するのは非常に簡単です。

@implementation OWCardView {
    NSMutableArray *pendingRects;
    BOOL isAnimating;
}

- (void)moveCard:(float)xPoint along:(float)yPoint {
    CGRect someRect = CGRectMake(xPoint, yPoint, 72, 96);
    if (!pendingRects) {
        pendingRects = [NSMutableArray array];
    }
    [pendingRects addObject:[NSValue valueWithCGRect:someRect]];
    [self startAnimatingIfNeeded];
}

- (void)startAnimatingIfNeeded {
    if (isAnimating)
        return;
    if (pendingRects.count == 0)
        return;
    CGRect rect = [[pendingRects objectAtIndex:0] CGRectValue];
    [pendingRects removeObjectAtIndex:0];

    isAnimating = YES;
    [UIView animateWithDuration:3.5 delay:0.3 options:UIViewAnimationCurveEaseOut animations:^{
        self.frame = rect;
    } completion:^(BOOL finished) {
        isAnimating = NO;
        [self startAnimatingIfNeeded];
    }];
}
于 2012-12-19T09:45:11.043 に答える
1

あなたが抱えている問題は、アニメーションが非同期であることです。

コードは、次のアニメーションを実行する前に各アニメーションが終了するのを待ちません。したがって、最初の 2 つの呼び出しを爆破して、3 番目のアニメーションをすぐに開始し、最初の 2 つの呼び出しをキャンセルして、最後のアニメーションのみが表示されるようにします。

アニメーションが終了した後に何かを行うには、完成したブロックを使用する必要があります。

これを行う簡単な方法は次のようになります...

[UIView animateWithDuration: 3.5
                      delay: 0.3
                    options: UIViewAnimationCurveEaseOut
                 animations: ^{ self.frame = CGRectMake(240, 355, 72, 96);}
                 completion: ^(BOOL finished) {
    [UIView animateWithDuration: 3.5
                          delay: 0.3
                        options: UIViewAnimationCurveEaseOut
                     animations: ^{ self.frame = CGRectMake(50, 355, 72, 96);}
                     completion: ^(BOOL finished) {
        [UIView animateWithDuration: 3.5
                              delay: 0.3
                            options: UIViewAnimationCurveEaseOut
                         animations: ^{ self.frame = CGRectMake(50, 50, 72, 96);}
                         completion: ^(BOOL finished) {
            //All finished
        }];
    }];
}];

これをある種の再帰関数に入れることもできますが、おそらくこれを行う方が簡単です。

もう 1 つの方法は、キー フレーム アニメーションを使用することです。パスとタイミングを文字通り段階的に構築し、「GO」と言うと、構築したアニメーションが実行されます。

これはおそらく今のところ簡単ですが、私は以前にこの種のものを使用したことがあります。

于 2012-12-19T09:39:49.643 に答える
1

3 番目のアニメーションは 1 番目と 2 番目のアニメーションをオーバーライドします

あなたはこれを使うことができます

- (void) moveCard:(CGPoint)Point1 point2:(CGPoint)Point2 point3:(CGPoint)Point3
{
    CGRect someRect = CGRectMake(Point2.x, Point2.y, 72, 96);

    [UIView animateWithDuration: 3.5
                          delay: 0.3
                        options: UIViewAnimationCurveEaseOut
                     animations: ^{ self.frame = someRect;}
                     completion: ^(BOOL finished) {
                         someRect = CGRectMake(Point2.x, Point2.y, 72, 96);
                         [UIView animateWithDuration: 3.5
                                               delay: 0.3
                                             options: UIViewAnimationCurveEaseOut
                                          animations: ^{ self.frame = someRect;}
                                          completion: ^(BOOL finished) {

                                              someRect = CGRectMake(Point3.x, Point3.y, 72, 96);
                                              [UIView animateWithDuration: 3.5
                                                                    delay: 0.3
                                                                  options: UIViewAnimationCurveEaseOut
                                                               animations: ^{ self.frame = someRect;}
                                                               completion: ^(BOOL finished) {



                                                               }];

                                          }];

                     }];
}
于 2012-12-19T09:41:54.460 に答える