0
votes

I noticed that after an orientation change from portrait to landscape, I'm not getting touchesBegan events for some parts of my view any longer. I suppose that this is because I'm not informing my UIView about the dimension change of my window's frame after the device rotation.

I'm setting up everything programmatically (UIWindow, UIViewController, UIView) like this:

myViewController = [[myUIViewController alloc] init];
myWindow = [[UIWindow alloc] initWithFrame: rect];
myView = [[myUIView alloc] initWithFrame: [myWindow bounds]];

[myViewController setView:myView];
[myWindow addSubview:myView];
[myWindow setFrame:rect];
[myWindow makeKeyAndVisible];

When I get the didRotateFromInterfaceOrientation notification, I'm updating the window frame like this:

[[[self view] window] setFrame:rect];

But after that, my UIView does no longer get touchesXXX events for all areas. It seems that only the areas of the previous frame are still reporting events. So my question: Is there anything else I need to do in didRotateFromInterfaceOrientation to inform my UIView about the dimension change?

Thanks for help!

EDIT: Do I have to reposition the UIView on didRotateFromInterfaceOrientation() or is this done automatically? I noticed that the "transform" property of my UIView is set to a transformation matrix when the orientation changes. However, this makes it very hard to reposition my view. The docs say that the "frame" property can't be used when a transformation is active, so I tried to modify the "center" property to reposition my view, but this also doesn't work correctly. I want to move the view to the top-left corner, so I set "center" to (screenwidth/2,screenheight/2) but it doesn't position the view correctly :( Any idea or info what must be done to get the events right in orientation mode?

2

2 Answers

0
votes

I have had this same problem, and I believe it is a frame issue.

I had to manually set the rects depending on orientation, as well as set the userInteractionEnabled on the main view, like:

if (appOrientation == 0)
    appOrientation = [UIApplication sharedApplication].statusBarOrientation;
if (appOrientation == UIInterfaceOrientationLandscapeLeft || appOrientation == UIInterfaceOrientationLandscapeRight) {

    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    myView.frame = CGRectMake(0, 0, 1024, 768);

} else {

    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    myView.frame = CGRectMake(0, 0, 768, 1024);
}

myView.userInteractionEnabled = YES;
0
votes

OK I know this is an old question but this is how I fixed this issue.

In my situation I had a storyboard with a view that would be displayed either in portrait or forced to landscape mode depending on a user setting.

My app displays the statusBar at all times except for when I'm showing this view.

To make this all work, the transformations had to be applied in the viewWillAppear method for one. I had the following code in the viewDidAppear method at first and that messed with the bounds for the touchesBegan event I guess.

Here's the viewWillAppear code:

- (void)viewWillAppear:(BOOL)animated
{
    // Hide the status bar
    [[UIApplication sharedApplication] setStatusBarHidden:YES];

    // This is to offset the frame so that the view will take the fullscreen once the status bar is hidden
    self.navigationController.navigationBar.frame = CGRectOffset(self.navigationController.navigationBar.frame, 0.0, -20.0);

    // If view is to be displayed in landscape mode
    if ([[NSUserDefaults standardUserDefaults] boolForKey:@"orientation"])
    {
        // Change status bar orientation
        [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft];

        // Turn the view 90 degrees
        [self.navigationController.view setTransform:CGAffineTransformMakeRotation(M_PI/2)];

        // Set the frame and the bounds for the view
        // Please Note: Frame size has to be reversed for some reason.
        [self.navigationController.view setFrame: CGRectMake(0,0,320,480)];
        [self.navigationController.view setBounds: CGRectMake(0,0,480,320)];

        // Make sure user can interact with view
        [self.navigationController.view setUserInteractionEnabled:YES];
    }
}

Any other thing that had to happen layout wise, have to happen in the viewDidAppear method. For instance I had an image that covered the whole view and the frame had to be set depending on the orientation. Setting the frame in the viewWillAppear gave weird results but the same code worked perfectly in viewDidAppear.

Hope this helps someone as I banged my head for 6 hours on this thing.