具有独立移动背景的自定义 segue
Custom segue with separate moving background
我想实现这个动画中的效果
我的应用程序中应该有两个(或更多)ViewControllers
具有自定义转场。过渡应该只是将新的 ViewController
向上移动。在背景中应该有一个图像,它会随着每个 segue 移动一点。
我总共考虑了 3 ViewControllers
。一个用于背景,处理背景移动并以模态方式显示 ViewController1
和 2
。但我不知道如何实现这一目标。有人有更好的方法或其他想法吗?
编辑
如果动画没有开始,请在另一个选项卡中打开 .gif 文件进行查看。
免责声明:这只是您可以做的事情的想法。您的情况听起来非常具体,自定义 segue 会很快变得非常复杂。所以这段代码可能无法完全满足您的需求。这让我可以深入了解我过去是如何解决类似问题的。
我不完全确定你的问题,但我可以告诉你我过去做过什么。
首先,我创建了一个继承自 UIStoryboardSegue 的自定义转场 class。我假设您知道如何设置故事板以使用 segue(即连接按钮事件或类似事件)。我为此提供的 class 是我的自定义转场 class.
在这个 class 的 perform
方法中,我利用 UIStoryboardSegue 的 sourceViewController
和 destinationViewController
属性来访问视图。我将目标视图控制器的视图添加到源视图控制器的视图层次结构中。这样我就可以把它动画化了。
对于您的情况,您可以创建一个 @protocol
来访问您的后台 属性,如下所示:
ViewControllerWithBackground.h
@protocol ViewControllerWithBackground
@property (nonatomic) IBOutlet UIImageView *backgroundImage;
@end
将该协议分配给将使用 segue 的每个视图控制器。在 segue 代码中,您可以在 class 的 perform
方法中移动背景 up/down 以执行 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;
}];
});
}];
}
}
可选
如果您需要代码来判断背景图像是否应该向上移动或向下移动,请不要忘记您已经子classed 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;
}
}
我想实现这个动画中的效果
我的应用程序中应该有两个(或更多)ViewControllers
具有自定义转场。过渡应该只是将新的 ViewController
向上移动。在背景中应该有一个图像,它会随着每个 segue 移动一点。
我总共考虑了 3 ViewControllers
。一个用于背景,处理背景移动并以模态方式显示 ViewController1
和 2
。但我不知道如何实现这一目标。有人有更好的方法或其他想法吗?
编辑 如果动画没有开始,请在另一个选项卡中打开 .gif 文件进行查看。
免责声明:这只是您可以做的事情的想法。您的情况听起来非常具体,自定义 segue 会很快变得非常复杂。所以这段代码可能无法完全满足您的需求。这让我可以深入了解我过去是如何解决类似问题的。
我不完全确定你的问题,但我可以告诉你我过去做过什么。
首先,我创建了一个继承自 UIStoryboardSegue 的自定义转场 class。我假设您知道如何设置故事板以使用 segue(即连接按钮事件或类似事件)。我为此提供的 class 是我的自定义转场 class.
在这个 class 的 perform
方法中,我利用 UIStoryboardSegue 的 sourceViewController
和 destinationViewController
属性来访问视图。我将目标视图控制器的视图添加到源视图控制器的视图层次结构中。这样我就可以把它动画化了。
对于您的情况,您可以创建一个 @protocol
来访问您的后台 属性,如下所示:
ViewControllerWithBackground.h
@protocol ViewControllerWithBackground
@property (nonatomic) IBOutlet UIImageView *backgroundImage;
@end
将该协议分配给将使用 segue 的每个视图控制器。在 segue 代码中,您可以在 class 的 perform
方法中移动背景 up/down 以执行 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;
}];
});
}];
}
}
可选
如果您需要代码来判断背景图像是否应该向上移动或向下移动,请不要忘记您已经子classed 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;
}
}