Как реализовать переход UIView

#iphone #ios #architecture #uiview

#iPhone #iOS #архитектура #uiview

Вопрос:

У меня есть приложение, у которого есть начальный экран с кнопкой «Пуск» на нем. Если вы нажмете на эту кнопку, вид изменится и появится новый вид, давайте назовем это основным видом.

Способ, которым я это реализовал, — это один контроллер просмотра для каждого представления. Теперь, когда я хочу добавить анимацию перехода, эта реализация вызывает проблемы. Например, я хочу использовать следующий код:

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

Но это ничего не делает. Чтение документации предполагает, что это работает только в том случае, если контроллер представления не изменяется. В документации нет примеров перехода curl down, при котором меняются контроллеры просмотра, поэтому я не уверен, что делать.

Когда я начал писать приложение, я прочитал рекомендации, и они предположили, что наличие одного контроллера просмотра для каждого представления является правильным способом выполнения того, что я делаю.

Теперь, каков правильный способ реализовать переход view, когда контроллер view тоже меняется? Большое спасибо за вашу помощь!

Редактировать: я ищу решение, при котором уничтожается первый контроллер просмотра.

Ответ №1:

Было предложено эффективно создать контроллер представления, использовать его представление, но затем игнорировать сам контроллер. Это не рекомендуется. В iOS вы хотите синхронизировать иерархию контроллера представления с вашей иерархией представлений. Поэтому любые методы, подобные предложенному, проблематичны. (Сессия 102 WWDC 2011, посвященная другой теме, сдерживанию контроллера просмотра, содержит продолжительное обсуждение важности синхронизации этих двух иерархий.)

Наиболее очевидная проблема заключается в том, что определенные события, в частности события поворота, не будут успешно переданы на ваш новый контроллер, и вы можете получить некоторые очень странные результаты. В приведенном выше коде также неясно, что происходит со старым представлением, которое вы удалили, как бы вы перешли обратно, как бы вы очистили ненужный теперь игровой контроллер, что бы произошло на didReceiveMemoryWarning , если бы вы были в игровом контроллере и т.д. Кажется, что это создает массу проблем.

Самое простое решение — применить стандартные pushViewController и / или presentViewController вызовы для перехода из одного представления в другое и просто анимировать эти переходы. Если у вас есть вопросы о любом из этих методов или о том, как анимировать в контексте этих методов, дайте мне знать.

Ответ №2:

Кстати, корень вашего вопроса заключался в том, как осуществлять переход между контроллерами просмотра. Вот старая коллекция переходов (некоторые для push-переходов, некоторые для модального перехода), с которыми я когда-то играл. Может быть, здесь есть что-то, что вы могли бы использовать?

 - (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

}
  

Ответ №3:

О’кей-доке, я нашел аккуратный способ достичь именно того, чего я хочу. Этот код, добавленный в метод, в котором я заменяю старый контроллер просмотра и view на новый, отлично работает:

 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!!

Комментарии:

1. Если кто-нибудь найдет в этом что-то неправильное с точки зрения дизайна, пожалуйста, опубликуйте это здесь, я приму это как правильный ответ на мой вопрос. Большое спасибо за вашу помощь!

2. Это действительно не лучшая идея с точки зрения дизайна. Смотрите мой ответ ниже.