繁体   English   中英

UIView动画在iOS 7中不起作用

[英]UIView animation not working in iOS 7

我正在一个示例项目中,其中有一个垂直scrollview和一个水平scrollview 垂直scrollview视图具有许多子视图。 scrollviewDidScroll我正在执行一些操作。 与此相关的是,我现在想在屏幕上可见该特定子视图时在垂直滚动视图中为该子视图设置动画。 为此,我正在做一个正确的计算。 动画如下:

子视图包含多个自定义视图。 我正在尝试以某个特定的时间顺序对每个视图进行动画处理(减小然后再增加该视图的Alpha值)(以便动画看起来是按顺序的)。 为此,我将通知发布到视图,并且动画序列和逻辑根据我想要的是完美的。

但是我遇到了一个问题,当我放置断点时,代码正在执行,但是动画没有显示。 如果我在停止滚动后发布通知,则动画会非常好。 但是我希望动画即使在滚动并且视图在屏幕上时也能发生。

我正在添加我的代码片段,如下所示:

SubView :(在我的scrollview

- (void)animateSequenceTemplate {
if (!hasSequenceTemplateAnimated) {
    [self performSelector:@selector(animateSequenceSlides) withObject:nil afterDelay:0];
    hasSequenceTemplateAnimated = YES;
}
else {
    return;
}
}

- (void)animateSequenceSlides {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:imageAsset forKey:@"assetMO"];
[[NSNotificationCenter defaultCenter]postNotificationName:AnimateSequenceSlide object:nil userInfo:userInfo];
}

上面的子视图中的子视图:

- (void)animateSlideView:(NSNotification *)notification {

NSDictionary *userInfo = notification.userInfo;
if ([userInfo objectForKey:@"assetMO"] == assetMO) {
    [[NSNotificationCenter defaultCenter]removeObserver:self name:AnimateSequenceSlide object:nil];

    CGFloat duration = 0.035;
    float delay = (self.slideCount * duration);
    CGFloat timeDelay = 0;


    [self performSelector:@selector(animationPhase1) withObject:nil afterDelay:delay];
    timeDelay = delay + duration;
    [self performSelector:@selector(animationPhase2) withObject:nil afterDelay:timeDelay];

    if (self.slideCount == (self.maxSlideCount - 1)) {
        timeDelay += duration * 18; //No animation till 18 frames
    }
    else {
        timeDelay += duration;
    }
    [self performSelector:@selector(animationPhase3) withObject:nil afterDelay:timeDelay];
    timeDelay += duration;
    [self performSelector:@selector(animationPhase4) withObject:nil afterDelay:timeDelay];
}
}

- (void)animationPhase1 {
[UIView animateWithDuration:0.035 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^ {
    [self setAlpha:0.85];
}completion:^(BOOL finished) {
}];
}

内部发生两种情况- (void)animateSequenceTemplate

  1. 我称之为[self animateSequenceSlides]; 在这种情况下,动画不会显示。
  2. [self performSelector:@selector(animateSequenceSlides) withObject:nil afterDelay:0.0f]; 在这种情况下,动画将显示出来,但是在scrollview静止之后。

我被迫使用执行选择器来使用UIView动画,因为如果删除它并使用嵌套的UIView动画块/或直接调用这些方法,则动画不会再次显示。 现在至少在我静止滚动后才显示出来。

我想提出解决方案的建议,或者对我可能犯的错误有任何猜测。

您有可能不在主队列上执行它。

dispatch_async(dispatch_get_main_queue, block())可能会有所帮助。 使用动画时,主队列是执行代码的唯一位置,这使动画发生。

编辑:

[self performSelector:@selector(animationPhase1) withObject:nil afterDelay:delay];

我不确定它在哪里发生,但我不认为在主线程上。 尝试这个:

[self performSelectorOnMainThread:@selector(animationPhase1) 
                       withObject:nil 
                    waitUntilDone:YES];

我不确定延迟,这就是为什么我更喜欢GCD功能和块。

终于,我得到了我的问题的解决方案,并且按预期工作得很好。

所做的更改:

  1. 从“ animateSequenceTemplate”中,直接调用“ animateSequenceSlides”方法
  2. 在上述“ animateSlideView”方法中,我没有使用执行选择器,而是创建了具有所需延迟的NSTimer对象,将其重复设置为NO,并在当前运行循环中添加了计时器
  3. 调用所有四个animationPhase方法的操作相同
  4. 代码可以正常工作

      - (void)animateSequenceTemplate { if (!hasSequenceTemplateAnimated && self.isSequenceSlideCreated) { hasSequenceTemplateAnimated = YES; [self animateSequenceSlides]; } } - (void)animateSlideView:(NSNotification *)notification { NSDictionary *userInfo = notification.userInfo; if ([userInfo objectForKey:@"assetMO"] == assetMO) { [[NSNotificationCenter defaultCenter]removeObserver:self name:AnimateSequenceSlide object:nil]; CGFloat duration = 0.035; float delay = (self.slideCount * duration); CGFloat timeDelay = 0; NSTimer *animate1 = [NSTimer scheduledTimerWithTimeInterval:delay target:self selector:@selector(animationPhase1) userInfo:nil repeats:NO]; [[NSRunLoop currentRunLoop]addTimer:animate1 forMode:NSRunLoopCommonModes]; timeDelay = delay + duration; NSTimer *animate2 = [NSTimer scheduledTimerWithTimeInterval:timeDelay target:self selector:@selector(animationPhase2) userInfo:nil repeats:NO]; [[NSRunLoop currentRunLoop]addTimer:animate2 forMode:NSRunLoopCommonModes]; if (self.slideCount == (self.maxSlideCount - 1)) { timeDelay += duration * 18; //No animation till 18 frames } else { timeDelay += duration; } NSTimer *animate3 = [NSTimer scheduledTimerWithTimeInterval:timeDelay target:self selector:@selector(animationPhase3) userInfo:nil repeats:NO]; [[NSRunLoop currentRunLoop]addTimer:animate3 forMode:NSRunLoopCommonModes]; timeDelay += duration; NSTimer *animate4 = [NSTimer scheduledTimerWithTimeInterval:timeDelay target:self selector:@selector(animationPhase4) userInfo:nil repeats:NO]; [[NSRunLoop currentRunLoop]addTimer:animate4 forMode:NSRunLoopCommonModes]; } } 

我对代码结构的好处不满意。 如果您有其他明智的做法,请分享。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM