development

네비게이션 컨트롤러 스택, 서브 뷰 또는 모달 컨트롤러를 사용하지 않고 뷰 컨트롤러의 애니메이션 변경?

big-blog 2020. 6. 20. 09:31
반응형

네비게이션 컨트롤러 스택, 서브 뷰 또는 모달 컨트롤러를 사용하지 않고 뷰 컨트롤러의 애니메이션 변경?


NavigationController에는 관리 할 ViewController 스택과 제한된 애니메이션 전환이 있습니다.

기존의보기 컨트롤러에 하위보기로보기 컨트롤러를 추가하려면 이벤트를 하위보기 컨트롤러에 전달해야합니다. 하위보기 컨트롤러는 관리하기가 어렵고 약간의 성가심이 있으며 일반적으로 구현할 때 나쁜 해킹처럼 느껴집니다 (Apple은 이 작업을 수행).

모달 뷰 컨트롤러를 다시 표시하면 뷰 컨트롤러가 다른 뷰 컨트롤러 위에 배치되며 위에서 설명한 이벤트 통과 문제가 없지만 실제로는 뷰 컨트롤러를 '스왑'하지 않고 스택합니다.

스토리 보드는 iOS 5로 제한되며 거의 이상적이지만 모든 프로젝트에서 사용할 수는 없습니다.

위의 제한없이 뷰 컨트롤러를 변경하고 애니메이션 전환을 허용하는 방법으로 SOLID CODE EXAMPLE을 제시 할 수 있습니까?

닫기 예제이지만 애니메이션은 없음 : 탐색 컨트롤러없이 여러 iOS 사용자 정의보기 컨트롤러를 사용하는 방법

편집 : Nav Controller 사용은 좋지만 슬라이드 효과가 아닌 애니메이션 전환 스타일이 있어야합니다.보기 컨트롤러가 완전히 스왑되어야합니다 (스택되지 않음). 두 번째 뷰 컨트롤러가 스택에서 다른 뷰 컨트롤러를 제거해야하는 경우 캡슐화되지 않은 것입니다.

편집 2 : iOS 4 가이 질문의 기본 OS 여야합니다. 스토리 보드를 언급 할 때 위의 내용을 분명히 했어야합니다.


편집 : 모든 방향에서 작동하는 새로운 답변. 원래 답변은 인터페이스가 세로 방향 일 때만 작동합니다. 이것은 다른 뷰가있는 뷰를 대체하는 b / c 뷰 전환 애니메이션으로, 창에 추가 된 첫 번째 뷰 아래의 레벨 (예 :) 이상이어야합니다window.rootViewController.view.anotherView.

내가 호출 한 간단한 컨테이너 클래스를 구현했습니다 TransitionController. https://gist.github.com/1394947 에서 찾을 수 있습니다 .

따로, 별도의 클래스 b / c로 구현하는 것이 더 쉽습니다. 재사용이 더 쉽습니다. 원하지 않으면 TransitionController클래스에 대한 필요성을 제거하면서 앱 델리게이트에서 동일한 로직을 직접 구현할 수 있습니다 . 그러나 필요한 논리는 동일합니다.

다음과 같이 사용하십시오.

앱 위임에서

// add a property for the TransitionController

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    MyViewController *vc = [[MyViewContoller alloc] init...];
    self.transitionController = [[TransitionController alloc] initWithViewController:vc];
    self.window.rootViewController = self.transitionController;
    [self.window makeKeyAndVisible];
    return YES;
}

모든 뷰 컨트롤러에서 새 뷰 컨트롤러로 전환하려면

- (IBAction)flipToView
{
    anotherViewController *vc = [[AnotherViewController alloc] init...];
    MyAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
    [appDelegate.transitionController transitionToViewController:vc withOptions:UIViewAnimationOptionTransitionFlipFromRight];
}

편집 : 아래의 원본 답변-portait 방향에서만 작동합니다

이 예제에서는 다음과 같은 가정을했습니다.

  1. rootViewController창에 뷰 컨트롤러가 할당되어 있습니다.

  2. 새보기로 전환하면 현재 viewController를 새보기를 소유 한 viewController로 바꾸려고합니다. 언제든지 현재 viewController 만 활성화됩니다 (예 : 할당 됨).

코드는 다른 방식으로 작동하도록 쉽게 수정할 수 있습니다. 요점은 애니메이션 전환 및 단일 뷰 컨트롤러입니다. 뷰 컨트롤러를에 할당하는 것 이외의 위치에 유지하지 마십시오 window.rootViewController.

앱 델리게이트에서 전환을 애니메이션으로 만드는 코드

- (void)transitionToViewController:(UIViewController *)viewController
                    withTransition:(UIViewAnimationOptions)transition
{
    [UIView transitionFromView:self.window.rootViewController.view
                        toView:viewController.view
                      duration:0.65f
                       options:transition
                    completion:^(BOOL finished){
                        self.window.rootViewController = viewController;
                    }];
}

뷰 컨트롤러에서의 사용 예

- (IBAction)flipToNextView
{
    AnotherViewController *anotherVC = [[AnotherVC alloc] init...];
    MyAppDelegate *appDelegate = (MyAppDelegate *)[UIApplication sharedApplication].delegate;
    [appDelegate transitionToViewController:anotherVC
                             withTransition:UIViewAnimationOptionTransitionFlipFromRight];
}

You can use Apple's new viewController containment system. For more in-depth information check out the WWDC 2011 session video "Implementing UIViewController Containment".

New to iOS5, UIViewController Containment allows you to have a parent viewController and a number of child viewControllers that are contained within it. This is how the UISplitViewController works. Doing this you can stack view controllers in a parent, but for your particular application you are just using the parent to manage the transition from one visible viewController to another. This is the Apple approved way of doing things and animating from one child viewController is painless. Plus you get to use all the various different UIViewAnimationOption transitions!

Also, with UIViewContainment, you do not have to worry, unless you want to, about the messiness of managing the child viewControllers during orientation events. You can simply use the following to make sure your parentViewController forwards rotation events to the child viewControllers.

- (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers{
    return YES;
}

You can do the following or similar in your parent's viewDidLoad method to setup the first childViewController:

[self addChildViewController:self.currentViewController];
[self.view addSubview:self.currentViewController.view];
[self.currentViewController didMoveToParentViewController:self];
[self.currentViewController.swapViewControllerButton setTitle:@"Swap" forState:UIControlStateNormal];

then when you need to change the child viewController, you call something along the lines of the following within the parent viewController:

-(void)swapViewControllers:(childViewController *)addChildViewController:aNewViewController{
     [self addChildViewController:aNewViewController];
     __weak __block ViewController *weakSelf=self;
     [self transitionFromViewController:self.currentViewController
                       toViewController:aNewViewController
                               duration:1.0
                                options:UIViewAnimationOptionTransitionCurlUp
                             animations:nil
                             completion:^(BOOL finished) {
                                   [aNewViewController didMoveToParentViewController:weakSelf];

                                   [weakSelf.currentViewController willMoveToParentViewController:nil];
                                   [weakSelf.currentViewController removeFromParentViewController];

                                   weakSelf.currentViewController=[aNewViewController autorelease];
                             }];
 }

I posted a full example project here: https://github.com/toolmanGitHub/stackedViewControllers. This other project shows how to use UIViewController Containment on some various input viewController types that do not take up the whole screen. Good luck


OK, I know the question says without using a navigation controller, but no reason not to. OP wasn't responding to comments in time for me to go to sleep. Don't vote me down. :)

Here's how to pop the current view controller and flip to a new view controller using a navigation controller:

UINavigationController *myNavigationController = self.navigationController;
[[self retain] autorelease];

[myNavigationController popViewControllerAnimated:NO];

PreferencesViewController *controller = [[PreferencesViewController alloc] initWithNibName:nil bundle:nil];

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration: 0.65];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:myNavigationController.view cache:YES];
[myNavigationController pushViewController:controller animated:NO];
[UIView commitAnimations];

[controller release];

Since I just happened across this exact problem, and tried variations on all the pre-existing answers to limited success, I'll post how I eventually solved it:

As described in this post on custom segues, it's actually really easy to make custom segues. They are also super easy to hook up in Interface Builder, they keep relationships in IB visible, and they don't require much support by the segue's source/destination view controllers.

The post linked above provides iOS 4 code to replace the current top view controller on the navigationController stack with a new one using a slide-in-from-top animation.

In my case, I wanted a similar replace segue to happen, but with a FlipFromLeft transition. I also only needed support for iOS 5+. Code:

From RAFlipReplaceSegue.h:

#import <UIKit/UIKit.h>

@interface RAFlipReplaceSegue : UIStoryboardSegue
@end

From RAFlipReplaceSegue.m:

#import "RAFlipReplaceSegue.h"

@implementation RAFlipReplaceSegue

-(void) perform
{
    UIViewController *destVC = self.destinationViewController;
    UIViewController *sourceVC = self.sourceViewController;
    [destVC viewWillAppear:YES];

    destVC.view.frame = sourceVC.view.frame;

    [UIView transitionFromView:sourceVC.view
                        toView:destVC.view
                      duration:0.7
                       options:UIViewAnimationOptionTransitionFlipFromLeft
                    completion:^(BOOL finished)
                    {
                        [destVC viewDidAppear:YES];

                        UINavigationController *nav = sourceVC.navigationController;
                        [nav popViewControllerAnimated:NO];
                        [nav pushViewController:destVC animated:NO];
                    }
     ];
}

@end

Now, control-drag to set up any other kind of segue, then make it a Custom segue, and type in the name of the custom segue class, et voilà!


I struggled with this one for a long time, and one of my issues is listed here, I'm not sure if you have had that problem. But here's what I would recommend if it must work with iOS 4.

Firstly, create a new NavigationController class. This is where we'll do all the dirty work--other classes will be able to "cleanly" call instance methods like pushViewController: and such. In your .h:

@interface NavigationController : UIViewController {
    NSMutableArray *childViewControllers;
    UIViewController *currentViewController;
}

- (void)transitionFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController duration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL))completion;
- (void)addChildViewController:(UIViewController *)childController;
- (void)removeChildViewController:(UIViewController *)childController;

The child view controllers array will serve as a store for all the view controllers in our stack. We would automatically forward all rotation and resizing code from the NavigationController's view to the currentController.

Now, in our implementation:

- (void)transitionFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController duration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL))completion
{
    currentViewController = [toViewController retain];
    // Put any auto- and manual-resizing handling code here

    [UIView animateWithDuration:duration animations:animations completion:completion];

    [fromViewController.view removeFromSuperview];
}

- (void)addChildViewController:(UIViewController *)childController {
    [childViewControllers addObject:childController];
}

- (void)removeChildViewController:(UIViewController *)childController {
    [childViewControllers removeObject:childController];
}

Now you can implement your own custom pushViewController:, popViewController and such, using these method calls.

Good luck, and I hope this helps!


UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UINavigationController *viewController = (UINavigationController *)[storyboard instantiateViewControllerWithIdentifier:@"storyBoardIdentifier"];
viewController.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentViewController:viewController animated:YES completion:nil];

Try This Code.


This code gives Transition from a view controller to another view controller which having a navigation controller.

참고URL : https://stackoverflow.com/questions/8146253/animate-change-of-view-controllers-without-using-navigation-controller-stack-su

반응형