【问题标题】:CoreAnimation: Transferring animating objects to next UIViewControllerCoreAnimation:将动画对象转移到下一个 UIViewController
【发布时间】:2013-03-16 00:48:26
【问题描述】:

我目前正在使用这个核心动画; (iOS 5,ARC)

- (void)onTimer
{
    // build a view from our image
    UIImageView* flakeView = [[UIImageView alloc] initWithImage:flakeImage];

    // use the random() function to randomize up our flake attributes
    int startX = round(random() % 320);
    int endX = startX; //round(random() % 320);
    double scale = 1 / round(random() % 100) + 1.0;
    double speed = 1 / round(random() % 100) + 1.0;

    // set the flake start position
    flakeView.frame = CGRectMake(startX, -100.0, 25.0 * scale, 25.0 * scale);
    flakeView.alpha = 0.8;

    // put the flake in our main view
    [self.view addSubview:flakeView];
    [self.view sendSubviewToBack:flakeView];

    [UIView beginAnimations:nil context:(__bridge void*)flakeView];
    // set up how fast the flake will fall
    [UIView setAnimationDuration:10 * speed];

    // set the postion where flake will move to
    flakeView.frame = CGRectMake(endX, 500.0, 25.0 * scale, 25.0 * scale);

    // set a stop callback so we can cleanup the flake when it reaches the
    // end of its animation
    [UIView setAnimationDidStopSelector:@selector(onAnimationComplete:finished:context:)];
    [UIView setAnimationDelegate:self];
    [UIView commitAnimations];

}
- (void)onAnimationComplete:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {

    UIImageView *flakeView = (__bridge UIImageView*)context;
    [flakeView removeFromSuperview];
    flakeView = nil;
}

火;

[NSTimer scheduledTimerWithTimeInterval:(0.3) target:self selector:@selector(onTimer) userInfo:nil repeats:YES];

使用此代码,有 10 片雪花出现,落下。

借助此代码和一些自定义视图转换,我试图使导航操作流畅。问题是我找不到将这些(动画)上下文转移到下一个 UIViewController 的正确方法,因此所有动画雪花将继续从它们离开的地方继续,而下一个 UIViewControllerNSTimer 将触发新的那些。

任何帮助和建议都将得到应用。

【问题讨论】:

  • 不清楚您要转移什么。您是否希望将实际的图像视图传输到下一个控制器?描述您正在寻找的视觉效果可能很有用。顺便说一句,您根本不应该使用这种动画方法。您应该在 iOS 4 或更高版本中使用基于块的方法。

标签: iphone ios objective-c core-animation


【解决方案1】:

也许您可以将您的上下文放在此类的私有扩展中。
点赞:@property (nonatomic,weak)IBOutlet UIImageView*context;

【讨论】:

    【解决方案2】:

    我怀疑您是否可以将正在制作动画的视图转移到另一个视图控制器。我怀疑当你从它的超级视图中删除它时,它会终止任何动画。

    您最好编写代码来跟踪在数组中动画的视图。当需要创建一个新的视图控制器时,查询每个图像视图层的presentationLayer并获取它的位置。然后从当前视图控制器中删除所有雪花视图,并将整个数组以及位置数组传递给新的视图控制器。然后在新视图控制器的 viewDidLoad 中,在它们之前的位置添加雪花视图数组,并开始动画到它们之前的结束位置,并启动动画计时器以开始添加更多雪花。

    【讨论】:

    • 我创建了一个单例(动画管理器)并且它运行良好。我会尽快发布答案。并且 +1 在数组上保存动画对象。干杯!
    • 另一种选择是简单地将雪花保存在具有自己的视图控制器的单独视图中,然后只需将雪花容器视图添加到接下来显示的任何视图中。
    • 经理是navigationController的代表。因此,当导航操作发生时,它只是将动画对象(来自数组)添加到新的视图控制器中。让我把代码:)
    • 刚刚添加了代码。让我知道是否有任何我可以改进以提高性能的部分...
    • 显然它可以在不重置动画的情况下正常工作:stackoverflow.com/questions/15449724/…
    【解决方案3】:

    .h 文件

    @interface BeanManager : NSObject <UINavigationControllerDelegate>
    {
        NSMutableDictionary *beanDictionary;
        UIViewController    *currentViewController;
        UIImage             *coffeebean;
        NSTimer             *beanTimer;
        NSInteger           contextTag;
        BOOL                isDebugging;
    }
    
    @property (nonatomic, retain) NSMutableDictionary   *beanDictionary;
    @property (nonatomic, retain) UIViewController      *currentViewController;
    @property (nonatomic) BOOL isDebugging;
    
    + (id)sharedManager;
    
    - (void)invalidate;
    - (void)validate;
    
    @end
    

    .m 文件

    + (id)sharedManager {
        static BeanManager *sharedMyManager = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedMyManager = [[self alloc] init];
        });
        return sharedMyManager;
    }
    
    - (id)init {
        if (self = [super init]) {
            coffeebean = [UIImage imageNamed:@"coffeebean"];
    
            // assign self as navigation controllers delegate
            AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
            [appDelegate.navigationController setDelegate:self];
    
            self.currentViewController = appDelegate.navigationController.visibleViewController;
    
            beanDictionary = [[NSMutableDictionary alloc] init];
    
            NSLog(@"%@ : Allocating",[self class]);
    
            [self validate];
        }
        return self;
    }
    
    - (void)dealloc {
        if (isDebugging) {
            NSLog(@"%@: Deallocating", [self class]);
        }
    }
    
    #pragma mark - UINavigationController
    - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
        if (isDebugging) {
            NSLog(@"%@: Pushing %d beans to new view",[self class], [[beanDictionary allKeys] count]);
        }
        for (UIImageView *animatingBeans in [beanDictionary allValues]) {
            [viewController.view addSubview:animatingBeans];
            [viewController.view sendSubviewToBack:animatingBeans];
        }
    
        self.currentViewController = viewController;
    }
    
    #pragma mark - Internals
    - (void)validate
    {
        beanTimer = [NSTimer scheduledTimerWithTimeInterval:(0.3) target:self selector:@selector(onTimerWithBlock) userInfo:nil repeats:YES];
    }
    
    - (void)invalidate
    {
        [beanTimer invalidate];
    }
    
    - (void)onTimerWithBlock
    {
        // build a view from our flake image
        UIImageView* beanView = [[UIImageView alloc] initWithImage:coffeebean];
    
        // use the random() function to randomize up our flake attributes
        int startX = round(random() % 320);
        int endX = startX; //round(random() % 320);
        double scale = 1 / round(random() % 100) + 1.0;
        double speed = 1 / round(random() % 100) + 1.0;
    
        // set the flake start position
        beanView.frame = CGRectMake(startX, -100.0, 25.0 * scale, 25.0 * scale);
        beanView.alpha = 0.8;
        beanView.tag = contextTag; 
    
        [beanDictionary setObject:beanView forKey:[NSString stringWithFormat:@"%d",contextTag]];
    
        if (contextTag > 1000) {
            contextTag = 0;
        }
        contextTag++;
    
        // put the flake in our main view
        [self.currentViewController.view addSubview:beanView];
        [self.currentViewController.view sendSubviewToBack:beanView];
    
        [UIView animateWithDuration:(speed * 10) animations:^{
    
            [beanView setFrame:CGRectMake(endX, 500.0, 25.0 * scale, 25.0 * scale)];
    
        } completion:^(BOOL finished) 
        {
            [beanDictionary removeObjectForKey:[NSString stringWithFormat:@"%d",beanView.tag]];
            if (isDebugging) {
                NSLog(@"%@: Dictionary Count %d",[self class], [[beanDictionary allKeys] count]);
            }
            [beanView removeFromSuperview];
        }];
    }
    

    这段代码似乎完成了这项工作。到目前为止,我没有将它用作单例,但如果我将扩展此代码,它应该作为单例实现,只是为了澄清。而且我使用的是NSDictionary 而不是NSArray,它可以按原样工作,我再次认为我可能会为其添加一些功能,所以我将其设为NSDictionary

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多