如何在执行sendSubviewToBack之前强制完成视图动画?

时间:2015-01-14 15:57:01

标签: ios animation uiview

我正在构建一个页面浏览器,可以将页面设置为“纸张”和“纸张”。从一堆文件上拉下来。为了保持流畅的动画,我使用了3个相互叠加的UIViews。这三个视图包含当前页面(在顶部),上一页面(在中间)和下一页面(在底部)。

在下面的代码中,我想将顶视图向右拖动,显示下面的上一页。这很好用。但是,之后我需要将首页移动到堆栈的底部,以便在下次用户执行页面翻转时准备三个视图的堆栈。我使用sendSubviewToBack方法。

我的问题是,一旦动画开始,ViewSample [Top]就会被发送到堆栈的底部。在将动画发送到堆栈底部之前,如何强制完成动画(以便ViewSample [Top]完全移出屏幕)?

ViewSample[Top].center = CGPointMake(x,y);

[UIView animateWithDuration:0.5
        animations:^
{ 
   ViewSample[Top].center = CGPointMake(x+w,y); //slide away to the right 
}
completion:^(BOOL finished)
{ 
}
];

[self.MainView sendSubviewToBack:ViewSample[Top]];

修改

我遇到了一个与我的问题有关的非常特殊的行为。 我按照你的建议,发现“完成”中的行为。动画部分取决于变量' top'当它被设置为AFTERWARDS:

ViewSample[Top].center = CGPointMake(x,y);

[UIView animateWithDuration:0.5
        animations:^
{ 
   ViewSample[Top].center = CGPointMake(x+w,y); //slide away to the right 
}
completion:^(BOOL finished)
{ [self.MainView sendSubviewToBack:ViewSample[Top]];
}
];

Top++; // THIS COMMAND AFFECTS THE LINE ABOVE!!!

换句话说,当我添加一行' Top ++;'另一个View被移回堆栈,即使语句sendSubviewToBack是第一个。这对我来说非常困惑。这有意义吗?这是一个错误吗?

3 个答案:

答案 0 :(得分:2)

其他答案正确地确定了问题。您更新的代码遇到的问题是执行顺序问题:

因为完成仅在动画完成后执行,所以您的代码实际按以下顺序执行:

  1. ViewSample[Top].center = CGPointMake(x,y);
  2. ViewSample[Top].center = CGPointMake(x+w,y);
  3. Top++;
  4. [self.MainView sendSubviewToBack:ViewSample[Top]];
  5. 有两种可能的解决方案。您可以将视图存储在变量中,这样您在所有调用中都可以看到相同的视图,或者您可以延迟设置Top的值直到完成。

    选项1

    UIView *viewMovingFromTopToBottom = ViewSample[Top];
    
    viewMovingFromTopToBottom.center = CGPointMake(x,y);
    
    [UIView animateWithDuration:0.5 animations:^{ 
        viewMovingFromTopToBottom.center = CGPointMake(x+w,y); //slide away to the right 
    } completion:^(BOOL finished) {
        [self.MainView sendSubviewToBack:viewMovingFromTopToBottom];
    }];
    
    Top++;
    // Other code that depends on the new value of Top...
    

    选项2

    ViewSample[Top].center = CGPointMake(x,y);
    
    [UIView animateWithDuration:0.5 animations:^{ 
        ViewSample[Top].center = CGPointMake(x+w,y); //slide away to the right 
    } completion:^(BOOL finished) {
        [self.MainView sendSubviewToBack:ViewSample[Top]];
        Top++;
        // Other code that depends on the new value of Top...
    }];
    

    哪个选项对您最有意义取决于您正在做什么。如果您将动画链接在一起,则可能需要将大部分代码移动到完成块中以延迟它直到幻灯片动画完成。如果您需要立即完成大量工作而不依赖于动画,则可能需要使用选项1来配置动画并继续。或者你可能想要混合。

答案 1 :(得分:0)

使用completion块:

 ViewSample[Top].center = CGPointMake(x,y);

[UIView animateWithDuration:0.5
        animations:^
{ 
  ViewSample[Top].center = CGPointMake(x+w,y); //slide away to the right 
}
completion:^(BOOL finished)
{
  [self.MainView sendSubviewToBack:ViewSample[Top]];
}
];

答案 2 :(得分:0)

Brian Nickel的第一个建议(局部变量)就是这个伎俩。但是,有一点需要注意:你必须按照陈述的顺序小心。这不起作用:     [self.MainView addSubview:LocalView];     LocalView = View [1]; ......这样做:     LocalView = View [1];     [self.MainView addSubview:LocalView]; 我首先得到了顶级版本,只显示空白视图。

因此,一种工作方法是使用三个全局视图来执行页面缓存,并为动画使用两个本地视图。本地视图按适当顺序堆叠,从全局视图复制数据,然后执行动画。