1

より具体的には、UIScrollViewが埋め込まれた がありUIImageViewます。

「アニメーション」フレームを記述するオブジェクトがあります

@class AnimationFrame

@property (nonatomic,strong) UIImage *image;
@property (nonatomic) CGRect zoomToRectInImage;
@property (nonatomic) CGFloat duration;

@end

animationframe.imageイメージビューが現在の画像をスワップしてからその位置にズームするように、フレームを互いにチェーンしたいと思います。

私はこのようなことを考えました(疑似コード):

-(void)animateImageView
{
      // imagine these were created before hand
      NSArray *myAnimationFrames = @[frame1,frame2,frame3,frame4,frame5]; 

      // now iterate through the frames and start the animation
      for (AnimationFrame *frame in myAnimationFrames)
      {
          self.scrollview.zoomScale = 1.0;
          self.imageView.image = frame.image;
          [self.scrollview zoomToRect:frame.zoomToRectInImage animated:YES];
      }
}

しかし、画像の変更とズームの同期に問題があります。

それらが重複していないことを確認するにはどうすればよいですか?

4

3 に答える 3

2

フレームの配列が動的であるか、配列が大きくなると、タスクの継続を実装するのが少し扱いに​​くくなります。

サードパーティのライブラリ (つまり、1 つのクラスのみ) を使用すると、次のようになります。

まず、アニメーション タスクを次のように定義します。

- (RXPromise*) animationTaskWithFrame(AnimationFrame* frame) 
{
    RXPromise* promise = [RXPromise new];
    [UIView animateWithDuration:0.5 animations:^{
        ...  // animation block 
    }
    completion:^(BOOL finished) {
         [promise fulfillWithValue:@"OK"];
    }];

    return promise;
}

次に、NSArray のカテゴリを実装したと仮定します。

typedef RXPromise* ^(unary_async_t)(id param);

@interface NSArray (RXExtension)
- (RXPromise*) forEachApplyTask:(unary_async_t)task;
@end

次のようにフレームを実行できます。

-(void)animateImageView
{
    NSArray* myAnimationFrames = @[frame1,frame2,frame3,frame4,frame5]; 

    // start the animations asynchronously:
    self.myAnimationFramesPromise = [myAnimationFrames forEachApplyTask:^RXPromise*(id frame){
        return [self animationTaskWithFrame:frame];
    }];

    // When finished, then:
    self.myAnimationFramesPromise.then(^id(id result){
        // All animations finished.
        NSLog(@"Result: %@", result);  // prints @"Finished"
        return nil;
    }, nil /* error handler*/);

}

すべてが終了する前にアニメーションをキャンセルしたい場合:

// elsewhere:

- (void) viewWillDisappear:(BOOL)animated {

     [self.myAnimationFramesPromise cancel];
}

カテゴリの実装を以下に示します。これは一般的な実装であり、配列内の各要素に対してブロックタスクで指定された非同期関数を順番にシリアルに呼び出すだけであることに注意してください。したがって、これはアニメーションを実行するためだけでなく、他の場所でも再利用できるツールです。

static RXPromise* do_apply_each(NSEnumerator* iter, RXPromise* promiseResult, unary_async_t task)
{
    if (promiseResult.isCancelled) {
        return promiseResult;
    }
    id obj = [iter nextObject];
    if (obj == nil) {
        [promiseResult fulfillWithValue:@"Finished"];
        return promiseResult;
    }
    promiseResult = task(obj).then(^id(id result){
        return do_apply_each(iter, promiseResult, task);
    }, ^id(NSError*error){
        return error;
    });
    return promiseResult;
}


@implementation NSArray (RXExtension)

- (RXPromise*) forEachApplyTask:(unary_async_t)task {
    RXPromise* promise = [RXPromise new];
    NSEnumerator* iter = [self objectEnumerator];
    return do_apply_each(iter, promise, task);
}

@end

RXPromise は GitHub: RXPromiseで入手できます。開示:私は著者です。

于 2013-08-29T11:55:05.203 に答える
2

このコードを試して、

[UIView animateWithDuration:0.5
                 animations:^
{ 
//do the changes of the view after the animation

}
completion:^(BOOL finished)
 {
    //anything to be done after animation
 }
 ];
于 2013-08-29T08:41:18.587 に答える
-1

UIView には次のメソッドがあり、これらのメソッドを使用して要件を達成できます。

[UIView animateWithDuration: animations:];
[UIView animateWithDuration: animations: completion:];
[UIView animateWithDuration: delay: options: animations: completion:]
于 2013-08-29T08:50:56.513 に答える