简体   繁体   English

UIView动画在iOS 7中不起作用

[英]UIView animation not working in iOS 7

I am working on a sample project in which I have a vertical scrollview and a horizontal scrollview . 我正在一个示例项目中,其中有一个垂直scrollview和一个水平scrollview The vertical scrollview has a number of subviews. 垂直scrollview视图具有许多子视图。 In scrollviewDidScroll I am performing some actions. scrollviewDidScroll我正在执行一些操作。 Along with this I now want to animate a subview inside the vertical scrollview when that particular subview is visible on the screen. 与此相关的是,我现在想在屏幕上可见该特定子视图时在垂直滚动视图中为该子视图设置动画。 For this I am doing a certain calculation which is correct. 为此,我正在做一个正确的计算。 The animation is as follows: 动画如下:

The subview contains multiple custom views. 子视图包含多个自定义视图。 I am trying to animate(reducing and then again increasing alpha value for the view) each of these views in some particular time sequence(so that the animation looks to be in sequence). 我正在尝试以某个特定的时间顺序对每个视图进行动画处理(减小然后再增加该视图的Alpha值)(以便动画看起来是按顺序的)。 For this I am posting notification to the views and the animation sequence and logic is perfect according to what I want. 为此,我将通知发布到视图,并且动画序列和逻辑根据我想要的是完美的。

But I am facing the problem that the code is executing when I put the breakpoint, but the animation does not show up. 但是我遇到了一个问题,当我放置断点时,代码正在执行,但是动画没有显示。 In case if I post the notification after I stop scrolling then the animation happens perfectly fine. 如果我在停止滚动后发布通知,则动画会非常好。 But I want is the animation to happen even when I am scrolling and the view is on screen. 但是我希望动画即使在滚动并且视图在屏幕上时也能发生。

I am adding my code snippet as below: 我正在添加我的代码片段,如下所示:

SubView : (Inside my scrollview ) 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];
}

Subviews inside the above subview: 上面的子视图中的子视图:

- (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) {
}];
}

There occurs two scenarios inside - (void)animateSequenceTemplate : 内部发生两种情况- (void)animateSequenceTemplate

  1. I call as [self animateSequenceSlides]; 我称之为[self animateSequenceSlides]; . In this case the animation does not show up. 在这种情况下,动画不会显示。
  2. [self performSelector:@selector(animateSequenceSlides) withObject:nil afterDelay:0.0f]; . In this case the animation shows up but after the scrollview rests. 在这种情况下,动画将显示出来,但是在scrollview静止之后。

I am compelled to use the UIView animation using perform selector because if I remove this and use either nested UIView animate blocks / or directly call these methods, then again animation does not show up. 我被迫使用执行选择器来使用UIView动画,因为如果删除它并使用嵌套的UIView动画块/或直接调用这些方法,则动画不会再次显示。 Now at lease it shows up after the I rest scrolling. 现在至少在我静止滚动后才显示出来。

I would like advice on a solution or any guess on what mistake I might be making. 我想提出解决方案的建议,或者对我可能犯的错误有任何猜测。

It possible, that you executing it not on the main queue. 您有可能不在主队列上执行它。

dispatch_async(dispatch_get_main_queue, block()) might help. dispatch_async(dispatch_get_main_queue, block())可能会有所帮助。 When working with animation, main queue the only place for executing code, that makes animation happen. 使用动画时,主队列是执行代码的唯一位置,这使动画发生。

EDIT: 编辑:

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

I'm not sure, where it happens, but I don't think on main thread. 我不确定它在哪里发生,但我不认为在主线程上。 Try this: 尝试这个:

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

I'm not sure about delay, that's why I prefer GCD functions and blocks. 我不确定延迟,这就是为什么我更喜欢GCD功能和块。

Finally, i got the solution to my question and it is working very fine as expected. 终于,我得到了我的问题的解决方案,并且按预期工作得很好。

Changes Made: 所做的更改:

  1. From "animateSequenceTemplate", calling "animateSequenceSlides" method directly 从“ animateSequenceTemplate”中,直接调用“ animateSequenceSlides”方法
  2. In "animateSlideView" method mentioned above, instead of using perform selector I created NSTimer object with the required delay, repeat set to NO, and adding the timer in the current run loop 在上述“ animateSlideView”方法中,我没有使用执行选择器,而是创建了具有所需延迟的NSTimer对象,将其重复设置为NO,并在当前运行循环中添加了计时器
  3. Did the same for calling all the four animationPhase methods 调用所有四个animationPhase方法的操作相同
  4. Code works fine as accepted 代码可以正常工作

      - (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]; } } 

I am not satisfied with the goodness of the code structure. 我对代码结构的好处不满意。 If you think of any other smart way of doing it, please share. 如果您有其他明智的做法,请分享。

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

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