1

更具体地说,我有UIScrollView一个嵌入式UIImageView.

我有一个描述“动画”框架的对象

@class AnimationFrame

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

@end

我想将帧链接在一起,以便 imageview 将当前图像交换到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

试试这个代码,

[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 回答
2

如果您的帧数组是动态的,或者数组变大,则任务延续变得有点难以实现。

在第三方库(好吧,只有一个类)的帮助下,它看起来像这样:

首先,定义一个动画任务如下:

- (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 回答
-1

UIView 有以下方法,您可以利用这些方法来实现您的要求。

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