Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Views Not Resizing After Rotation In Custom Container Controller

I've made a test app to familiarize myself with making a custom container view controller. If I rotate the device when the app first starts or after switching to a different view controller, the new view resizes to take up the whole screen, as I intended. However, if I rotate after the app starts, and then switch to a new view controller, the view keeps its portrait size instead of getting shorter and wider (actually it's slightly different -- it goes from 320,460 to 300,480). The master view controller is alloc init'd in the app delegate (no xib) and set as the window's root view controller. Here is the code I have in my MasterViewController (the custom container controller):

- (void)viewDidLoad {
    [super viewDidLoad];
    WelcomeController *welcome = [[WelcomeController alloc] initWithNibName:@"ViewController" bundle:nil];
    self.currentController = welcome;
    [self addChildViewController:welcome];
    [self.view addSubview:welcome.view];

    UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeft:)];
    swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
    [self.view addGestureRecognizer:swipeLeft];
}


- (void)swipeLeft:(UISwipeGestureRecognizer *)gesture {
    if (gesture.state == UIGestureRecognizerStateRecognized) {
        UIActionSheet *sheet =[[UIActionSheet alloc] initWithTitle:@"Select A Destination" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"welcome",@"Play",@"Scores", nil];
        [sheet showInView:self.view];
    }
}

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    switch (buttonIndex) {
        case 0:{
            if ([self.currentController class] != [WelcomeController class] ) {
                WelcomeController *welcome = [[WelcomeController alloc] initWithNibName:@"ViewController" bundle:nil];
                [self addChildViewController:welcome];
                [self moveToNewController:welcome];
            }
            break;
        }
        case 1:{
            if ([self.currentController class] != [PlayViewController class] ) {
                PlayViewController *player = [[PlayViewController alloc] initWithNibName:@"PlayViewController" bundle:nil];
                [self addChildViewController:player];
                [self moveToNewController:player];
            }
            break;
        }
        case 2:{
            if ([self.currentController class] != [HighScores class] ) {
                HighScores *scorer = [[HighScores alloc] initWithNibName:@"HighScores" bundle:nil];
                [self addChildViewController:scorer];
                [self moveToNewController:scorer];
            }
            break;
        }
        case 3:
            NSLog(@"Cancelled");
            break;

        default:
            break;
    }
}

-(void)moveToNewController:(id) newController {
    [self.currentController willMoveToParentViewController:nil];
    [self transitionFromViewController:self.currentController toViewController:newController duration:.6 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{}
     completion:^(BOOL finished) {
         [self.currentController removeFromParentViewController];
         [newController didMoveToParentViewController:self];
         self.currentController = newController;
     }];
}


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;//(interfaceOrientation == (UIInterfaceOrientationPortrait | UIInterfaceOrientationLandscapeLeft));
}

Any ideas why this is happening (I don't know if this means that the master view controller's view isn't resizing, but when I get this non-resizing behavior the gesture recognizer only responds in the narrow view, not over the whole screen)?

like image 266
rdelmar Avatar asked Nov 13 '22 23:11

rdelmar


1 Answers

You are not sending rotation messages to your child view controllers. At least not in the code you posted. After switching Child Controller you are even removing previous child from ChildViewControllers array with [self.currentController removeFromParentViewController] so even if you implement - (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers you have always only one ChildViewController in your ParentViewController.

I have got this working, so i will paste you how am i doing this. First i create all my ViewControllers, add them as child view controllers to ParentViewController. Then call didMoveToParentViewController: method.

//Controller1
Controller1 *c1 = [[Controller1 alloc] init];
c1.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self addChildViewController:c1];
[c1 didMoveToParentViewController:self];

//Controller2
Controller2 *c2 = [storyboard instantiateViewControllerWithIdentifier:@"c2"]; 
index.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self addChildViewController:c2];
[c2 didMoveToParentViewController:self];
c2.view.frame = m_contentView.frame;
[self.view addSubview:c2.view];   //It is in initial screen so set it right away
m_selectedViewController = c2;

//Controller3
Controller3 *c3 = [storyboard instantiateViewControllerWithIdentifier:@"c3"];
compare.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self addChildViewController:c3];
[c3 didMoveToParentViewController:self];

m_controllers = [NSArray arrayWithObjects:c1, c2, c3, nil];  //Hmm now i think this is not needed, I can access viewController directly from self.childViewControllers array

Then I implemented

- (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers
{
    return YES;
}

Switching to child view controller is done with this code

if (value < m_controllers.count)
{
    UIViewController *contentViewController = [m_controllers objectAtIndex:value];
    
    contentViewController.view.frame = m_contentView.frame;
    
    [self transitionFromViewController:m_selectedViewController toViewController:contentViewController duration:0 options:UIViewAnimationOptionTransitionNone animations:nil completion:^(BOOL finished) {
        m_selectedViewController = contentViewController;
        }
     ];
}

This should be enough. But i have got some issues with this so i send rotation messages to unactive Childs myself.

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    for (UIViewController *vc in m_controllers) 
    {
        if(vc != m_selectedViewController)
            [vc willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    }
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    for (UIViewController *vc in m_controllers) 
    {
        if(vc != m_selectedViewController)
            [vc willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
    }
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    for (UIViewController *vc in m_controllers) 
    {
        if(vc != m_selectedViewController)
            [vc didRotateFromInterfaceOrientation:fromInterfaceOrientation];
    }
}
like image 178
DaNY Avatar answered Dec 30 '22 09:12

DaNY