核心动画:将动画对象转移到下一个UIViewController

3

我目前正在使用这个核心动画;(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或更高版本中的基于块的方法。 - rdelmar
3个回答

0

头文件

@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


0
也许你可以将你的上下文放在这个类的私有扩展中。
例如:@property (nonatomic,weak)IBOutlet UIImageView*context;

0

我怀疑您是否可以将正在进行动画的视图转移到另一个视图控制器。我怀疑当您将其从其父视图中移除时,它将终止任何动画。

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


我创建了一个单例(动画管理器),它完美地工作着。我会尽快发布答案。并且在将动画对象保存在数组中方面给予+1。干杯! - Bartu
另一个选择是将您的雪花保留在单独的视图中,具有自己的视图控制器,然后只需将您的雪花容器视图添加到下一个显示的任何视图中。 - Aaron Brager
经理是navigationController的代表。因此,当导航操作发生时,它只需将动画对象(来自数组)添加到新的视图控制器中即可。让我放一下代码 :) - Bartu
刚刚添加了代码,请告诉我是否有任何部分可以改进以提高性能... - Bartu
显然,在不重置动画的情况下它可以正常工作:http://stackoverflow.com/questions/15449724/passing-an-animating-uiimageview-between-viewcontrollers-in-prepareforsegue - spring

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接