开发者

UINavigationController loading view incorrectly due to Orientation/Shake

开发者 https://www.devze.com 2023-03-19 21:52 出处:网络
Background: App has a shake to go home feature. Home view Only supports portrait. If you shake a bit harder than usual, the view that you are on starts to rotate (which is fine) , but then it detects

Background: App has a shake to go home feature. Home view Only supports portrait. If you shake a bit harder than usual, the view that you are on starts to rotate (which is fine) , but then it detects a shake and does a popViewControlller to the home view. When it does this it loads the navigation controller just fine, but the view under (the home content) gets loaded behind the bar and is stretched up (it's basically loading underneath the navigation bar, so it gets stretched up)

The back button handles this just fine from landscape to portrait (since its not mid transitions)

How should I go about handling this orientation change (from the shake) so I can pop back into the root view controller, without the view loading under the navigation bar?

Edit:What's happening is the content thinks that it has the entire view to load, so it stretches itself to take the entire screen, not realizing theres a navigationbar above it. I can tell since the images loading are stretched out

added a bounty of 50.

Edit Here's How I'm detecting Shakes and Popping

- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{

    if ( event.subtype == UIEventSubtypeMotionShake )
    {

            UINavigationController *navController = self.navigationController;

            [[self retain] autorelease];
            HomeViewController *home = [[HomeViewController alloc]init];
            [navController popViewControllerAnimated:YES];

     开发者_如何学运维       home.title =@"Home View Controller";
            [home release];     
        }

    if ( [super respondsToSelector:@selector(motionEnded:withEvent:)] )
        [super motionEnded:motion withEvent:event];
}

Here's my App Delegate:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    navController = [[UINavigationController alloc]init];
    [self.window addSubview:navController.view];

    HomeViewController *home = [[HomeViewController alloc]init];
    [[self home] setFrame:[[UIScreen mainScreen] applicationFrame]];

I'll include a mockup here.

Normal View:

UINavigationController loading view incorrectly due to Orientation/Shake

Stretched View After a Shake/Pop:

UINavigationController loading view incorrectly due to Orientation/Shake

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {

}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 
{}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return YES;
}


I'm a bit puzzled by your code so I'd really suggest starting from the beginning. As Lukya mentioned, there's no reason to recreate the HomeViewController. I'm also baffled by the "[[self retain] autorelease];" bit. That shouldn't be necessary unless you're doing something incorrectly elsewhere.

So I would start with this... In application:didFinishLaunchingWithOptions: do something like this:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
    {
        HomeViewController *home = [[[HomeViewController alloc] init] autorelease];
        UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:home] autorelease];
        [self.window addSubview:navController.view];
    }

The window will retain a your nav controller and the nav controller will retain your HomeViewController.

Then in motionEnded:withEvent: do something like:

    - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
    {
        if (event.subtype == UIEventSubtypeMotionShake)
        {
            [self.navigationController popViewControllerAnimated:YES];
        }
    }

That should be it.

If that does not work then can you give any other info? For example, does HomeViewController implement (and return YES) in shouldAutorotateToInterfaceOrientation:? If so, can you return no so it doesn't rotate since your first line says "Home view Only supports portrait"?

Edit: An example of willRotateToInterfaceOrientation:duration: and didRotateFromInterfaceOrientation: as well.

In the header for whatever controller you're detecting shakes in add a boolean:


    BOOL isRotating;

In your implementation file add the two UIViewController methods we want to override -- something like:


    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
        [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
        isRotating = YES;
    }

    - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
        [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
        isRotating = NO;
    }

Now, do something like this for your event handler:

    - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
    {
        if (event.subtype == UIEventSubtypeMotionShake && !isRotating)
        {
            [self.navigationController popViewControllerAnimated:YES];
        }
    }


in your home view controller's xib, go to the inspector for the view and set top bar as navigation bar.. and in view did load set self.navigationBarHidden = NO;...

NOTE: there are many thing wrong with the code you've posted.. but none of them causes the orientation problem... in fact this seems to be the only code you need in that method:

- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
    if (event.subtype == UIEventSubtypeMotionShake)
    {
        [navController popViewControllerAnimated:YES];
    }
}

so you might want to change this code as well..


Have you tried calling [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortrait animated:YES]; in your home view controller? You could also try to place this in where you detect a shake.


I have come across this issue with underlapping the navigation bar. I am not sure what causes it but you can work around it by calling,

[[self loadingView] setFrame:[[UIScreen mainScreen] applicationFrame]];

after the problem view is added to window in the application delegate.

0

精彩评论

暂无评论...
验证码 换一张
取 消