【问题标题】:How to implement UIView transition如何实现 UIView 过渡
【发布时间】:2011-08-12 00:03:47
【问题描述】:

我有一个应用程序,它有一个开始屏幕,上面有一个开始按钮。如果您点击该按钮,视图会发生变化并出现一个新视图,我们称之为主视图。

我实现它的方式是每个视图一个视图控制器。现在我想添加过渡动画,这个实现会导致问题。比如我想用下面的代码:

[UIView transitionFromView:startView toView: mainView duration: 2.0 
 options: UIViewAnimationOptionTransitionCurlDown completion: NULL];

但这并没有做任何事情。阅读文档表明这仅在视图控制器不更改时才有效。该文档没有任何视图控制器发生变化的向下卷曲过渡示例,因此我不确定该怎么做。

当我开始编写应用程序时,我阅读了指南,他们建议每个视图有一个视图控制器是做我正在做的事情的正确方法。

当视图控制器也发生变化时,实现视图转换的正确方法是什么?非常感谢您的帮助!

编辑:我正在寻找销毁第一个视图控制器的解决方案。

【问题讨论】:

    标签: iphone ios architecture uiview


    【解决方案1】:

    顺便说一句,您的问题的根源是如何在视图控制器之间进行转换。这是我曾经玩过的旧转换集合(一些用于推送转换,一些用于模态转换)。也许这里有一些你可以使用的东西?

    - (void)transitionToNewController
    {
        MyViewController *controller = [[MyViewController alloc] initWithNibName:@"MyView" bundle:nil];
    
    #if TRANSITIONTYPE == 1
    
        // pushViewController with push/slide from right via CATransition
    
        CATransition* transition = [CATransition animation];
    
        transition.duration = 0.3;
        transition.type = kCATransitionPush;
        transition.subtype = kCATransitionFromRight;
    
        [self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
        [self.navigationController pushViewController:controller animated:NO];
    #endif
    
    #if TRANSITIONTYPE == 2
    
        // pushViewController with flip using UIView begin/commitAnimations
    
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
        [UIView setAnimationDuration:0.75];
        [self.navigationController pushViewController:controller animated:NO];
        [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
        [UIView commitAnimations];
    #endif
    
    #if TRANSITIONTYPE == 3
    
        // pushViewController with flip using animation block
    
        [UIView animateWithDuration:0.5 
                         animations:^{
                             [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
                             [self.navigationController pushViewController:controller animated:NO];
                             [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
                         }
                         completion:nil];
    
    #endif
    
    #if TRANSITIONTYPE == 4
    
        // pushViewController with fade via CATransition
    
        CATransition* transition = [CATransition animation];
    
        transition.duration = 0.5;
        transition.type = kCATransitionFade;
    
        [self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
        [self.navigationController pushViewController:controller animated:NO];
    #endif
    
    #if TRANSITIONTYPE == 5
    
        // pushViewController with fade via animation block
    
        controller.view.alpha = 0.0f;
    
        [UIView animateWithDuration:0.5 
                         animations:^{
                             self.view.alpha = 0.0f;
                             controller.view.alpha = 1.0f;
                         }
                         completion:^(BOOL finished){
                             [self.navigationController pushViewController:controller animated:NO];
                             self.view.alpha = 1.0f; // reset the src alpha so it's there when you pop your view controller off
                         }];
    #endif
    
    #if TRANSITIONTYPE == 6
    
        // pushViewController Flip using UIView begin/commitAnimations
    
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
        [UIView setAnimationDuration:0.75];
        [self.navigationController pushViewController:controller animated:NO];
        [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:[self.self navigationController].view cache:NO];
        [UIView commitAnimations];
    #endif
    
    #if TRANSITIONTYPE == 7
    
        // pushViewController animation using CGAffine scale to look like we're zooming into the new view
    
        [self.view addSubview:controller.view];
        [controller.view setFrame:self.view.window.frame];
        [controller.view setTransform:CGAffineTransformMakeScale(0.5,0.5)];
        [controller.view setAlpha:1.0];
    
        [UIView animateWithDuration:0.5
                              delay:0.0
                            options:UIViewAnimationCurveEaseOut 
                         animations:^{
                             [controller.view setTransform:CGAffineTransformMakeScale(1.0,1.0)];
                             [controller.view setAlpha:1.0];
                         } 
                         completion:^(BOOL finished){
                             [controller.view removeFromSuperview];
                             [self.navigationController pushViewController:controller animated:NO];
                         }];
    #endif
    
    #if TRANSITIONTYPE == 8
    
        // presentViewController animation with slide from right by using CGAffineTransform
    
        self.view.transform = CGAffineTransformMakeTranslation(0, 0);
        controller.view.transform = CGAffineTransformMakeTranslation(self.view.frame.size.width, 0);
        [self.view addSubview:controller.view];
    
        [UIView animateWithDuration:4.0
                         animations:^{
                             //                         [self presentViewController:controller animated:NO completion:nil];
                             self.view.transform = CGAffineTransformMakeTranslation(self.view.frame.size.width, 0);
                             controller.view.transform = CGAffineTransformMakeTranslation(0, 0);
                         }
                         completion:^(BOOL finished){
                             [controller.view removeFromSuperview];
                             [self presentViewController:controller animated:NO completion:nil];
                         }
         ];
    #endif
    
    #if TRANSITIONTYPE == 9
    
        // presentViewController animation with slide from right by just animating frames
    
        float width = self.navigationController.view.frame.size.width;
    
        CGPoint right = controller.view.center;
        right.x += width;
        controller.view.center = right;
    
        [self.navigationController.view addSubview:controller.view];
    
        [UIView animateWithDuration:0.5
                         animations:^{
                             CGPoint left = self.navigationController.view.center;
                             left.x -= width;
                             self.navigationController.view.center = left;
                         }
                         completion:^(BOOL finished){
                             [controller.view removeFromSuperview];
                             [self presentViewController:controller animated:NO completion:nil];
                         }
         ];
    #endif
    
    #if TRANSITIONTYPE == 10
    
        // presentViewController animation with flipfromright
    
        [UIView animateWithDuration:4.0
                              delay:0.0 
                            options:UIViewAnimationOptionTransitionFlipFromRight 
                         animations:^{
                             [self.view addSubview:controller.view];
                         }
                         completion:^(BOOL finished){
                             [controller.view removeFromSuperview];
                             [self presentViewController:controller animated:NO completion:nil];
                         }];
    #endif
    
    #if TRANSITIONTYPE == 11
    
        // presentViewController with flip using UIView begin/commitAnimations
    
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
        [UIView setAnimationDuration:0.75];
        [self presentViewController:controller animated:NO completion:nil];
        [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO];
        [UIView commitAnimations];
    #endif
    
    #if TRANSITIONTYPE == 13
    
        // pushViewController with flip using animation block with transitionWithView
    
        controller.view.frame = self.view.window.frame;
    
        [UIView transitionWithView:self.view.superview 
                          duration:1.0
                           options:UIViewAnimationTransitionFlipFromRight
                        animations:^{
                            [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
                            [self.view.superview addSubview:controller.view];
                            [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
                        }
                        completion:^(BOOL finished){
                            [self.navigationController pushViewController:controller
                                                                 animated:NO];
                        }];
    
    #endif
    
    }
    

    【讨论】:

      【解决方案2】:

      有人建议您有效地创建一个视图控制器,使用它的视图,然后忽略控制器本身。不建议这样做。在 iOS 中,您希望保持视图控制器层次结构与视图层次结构同步。因此,任何像所提出的那样的技术都是有问题的。 (WWDC 2011 session 102,虽然在另一个主题上,视图控制器包含,对保持这两个层次结构同步的重要性进行了冗长的讨论。)

      最明显的问题是某些事件,尤其是旋转事件,不会成功传输到您的新控制器,并且您会得到一些非常奇怪的结果。上面的代码也不清楚您删除的旧视图会发生什么,您将如何转换回来,您将如何清理现在不必要的游戏控制器,如果您在游戏控制器中,didReceiveMemoryWarning 会发生什么等等。这似乎带来了很多问题。

      最简单的解决方案是应用标准的pushViewController 和/或presentViewController 调用以从一个视图转到另一个视图,并为这些转换设置动画。如果您对其中任何一种方法或如何在这些方法的上下文中制作动画有疑问,请告诉我。

      【讨论】:

        【解决方案3】:

        Okey-doke,我找到了一种巧妙的方法来实现我想要的。这段代码添加在我用新的视图控制器和视图交换旧视图控制器的方法中,效果很好:

        GameViewController *game = [[GameViewController alloc] init];
        UIView *currentView = [currentViewController view];
        // remove the current view and replace with myView1
        [currentView removeFromSuperview];
        // set up an animation for the transition between the views
        CATransition *animation = [CATransition animation];
        [animation setDuration:0.5];
        [animation setType:kCATransitionPush];
        [animation setSubtype:kCATransitionFromBottom];
        [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; 
        [[window layer] addAnimation:animation forKey:@"SwitchToView1"];    
        [self setCurrentViewController: game];
        [window addSubview:[currentViewController view]];
        [game release];
        

        非常感谢HERE!!

        【讨论】:

        • 如果有人从设计的角度发现这有问题,请在此处发布,我将接受它作为我问题的正确答案。非常感谢您的帮助!
        • 从设计的角度来看,这确实不是一个好主意。请参阅下面的答案。
        猜你喜欢
        • 2012-02-18
        • 2013-06-27
        • 2012-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-04
        相关资源
        最近更新 更多