自定义segue具有单独的移动背景

时间:2015-01-08 19:51:29

标签: uiviewcontroller segue transition modalviewcontroller

我想达到像这个动画一样的效果

Segue Animation

我的应用中应该有两个(或更多)ViewControllers具有自定义segue。过渡应该只是移动新的ViewController。在背景中应该有一个图像,每个segue都会移动一点。

我总共考虑了3 ViewControllers。一个用于背景,处理背景移动并以模态方式显示ViewController12。但我不知道如何实现这一目标。有没有人有更好的方法或其他想法?

修改 如果动画未启动,请在另一个选项卡中打开.gif以查看它。

1 个答案:

答案 0 :(得分:1)

免责声明:这只是您可以做的事情的想法。你的情况非常具体,而且自定义segue可以非常快速地变得非常复杂。因此,此代码可能无法完全满足您的需求。这提供了我过去如何解决类似问题的见解。


我不完全确定你的问题,但我可以告诉你我过去所做的事情。

首先,我创建一个继承自UIStoryboardSegue的自定义segue类。我将假设您知道如何设置故事板以使用segue(即连接按钮事件或类似事件)。我给出的课程是我自定义的segue类。

在这个类的perform方法中,我正在使用UIStoryboardSegue的sourceViewControllerdestinationViewController属性来访问视图。我将目标视图控制器的视图添加到源视图控制器的视图层次结构中。这样我就可以为它制作动画。

对于您的情况,您可以创建一个@protocol来访问您的背景属性,如下所示:

<强> ViewControllerWithBackground.h

@protocol ViewControllerWithBackground

@property (nonatomic) IBOutlet UIImageView *backgroundImage;

@end

将该协议分配给将使用segue的每个视图控制器。在segue代码中,您可以在类的perform方法中向上/向下移动背景以执行segue,如下所示:

自定义UIStoryboardSegue方法

- (void)perform {
    UIViewController *sourceViewController = self.sourceViewController;
    UIViewController *destinationViewController = self.destinationViewController;

    if ([self.sourceViewController conformsToProtocol:@protocol(ViewControllerWithBackground)] &&
            [self.destinationViewController conformsToProtocol:@protocol(ViewControllerWithBackground)]) {

        UIViewController<ViewControllerWithBackground> *sourceViewController = (UIViewController<ViewControllerWithBackground> *)self.sourceViewController;
        UIViewController<ViewControllerWithBackground> *destinationViewController = (UIViewController<ViewControllerWithBackground> *)self.destinationViewController;

        // Remove the existing view from the frame so we can animate it separately
        UIView *sourceView = sourceViewController.view;

        // Place a container view onto the frame that will contain the destination view and the current view
        sourceViewController.view = [[UIView alloc] initWithFrame:sourceView.frame];

        // Add the destination view controller's view and the place the source view on top of it so it's hidden
        [sourceViewController.view addSubview:destinationViewController.view];
        [sourceViewController.view addSubview:sourceView];

        // Set the final destination for the background image (i.e. where do you want it to end up in the destination view)
        CGRect currentBackgroundFrame = sourceViewController.backgroundImage.frame;
        CGRect finalBackgroundPosition = CGRectMake(0, 0, currentBackgroundFrame.size.width, currentBackgroundFrame.size.height); // ADD X,Y VALUES TO ANIMATE IT TO HERE

        // We are setting the background image's frame for the destination view controller here. (Remember: it's hidden the source view controller's view right now)
        destinationViewController.backgroundImage.frame = finalBackgroundPosition;

        // Animate everything
        [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
            // We are animating the original view's background image only
            sourceViewController.backgroundImage.frame = finalBackgroundPosition;

            // OTHER ANIMATION VALUES HERE

        } completion:^(BOOL finished) {
            // We have to dispatch because there will be unbalanced calls for begin/end transition because this transition hasn't finished executing
            dispatch_async(dispatch_get_main_queue(), ^(void){
                [sourceViewController presentViewController:destinationViewController animated:NO completion:^{
                    // Reset the view hierarchy to the original for unwinding (optional)
                    sourceViewController.view = sourceView;
                }];
            });

        }];

    }
}

<强>可选

如果您需要代码能够判断背景图像是上移还是下移,请不要忘记您已经将segue子类化,因此您可以将视图控制器的prepareForSegue:sender:方法中的信息传递给您自定义segue的perform方法如下:

源视图控制器示例

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    // Code that tells me this event requires the background to animate like it's moving up instead of down

    if ([segue isKindClass:[CustomStoryBoardBackgroundThingSegue class]]) {
        CustomStoryBoardBackgroundThingSegue *customSegue = (CustomStoryBoardBackgroundThingSegue *)segue;
        segue.animateUp = YES;
    }
}