简体   繁体   中英

iOS8 touch position is limited in Landscape, as if window is Portrait on one side?

I'm having a bizarre problem here with iOS8. I've been googling and bashing my head against a wall for a couple of days with no luck. I'm not exactly sure how to even explain it, but here goes...

Apps have been running fine under iOS7, but now compiling using xCode 6/iOS8 I'm having a few strange orientation problems. I'm not using a xib file, but instead creating a window and view programatically. I'm running OpenGL in the view, and then handling everything else inside OpenGL. So, I'm collecting touches and passing them to my GL routines. All has been fine forever, til now.

Now with iOS8 it seems as if the "touch window" is rotating itself so that touches in Landscape are limited to one side of the screen, as if the display window is Landscape, but the touches are all within a Portrait window that is set to on one side of the screen.

What seems bizarre is that touches come through to the view all over the screen as normal, but the Y value stops at 320 and goes no further. The X acts normally. If I turn the device to Portrait (the view controller does not auto rotate), it all works, but in Landscape it switches to this strange behaviour.

I've tried all I can think of without any changes, and am not sure where to begin to work out why this could be happening. Any advice would be greatly appreciated.

On iOS8, UIScreen is now interface oriented. In some (or should I say all of) libraries before iOS8, some checks were done to adjust that lack and swap width and height when the application was in landscape.

You should look at some code that makes some rotation and remove it.

-[UIScreen bounds] ,
-[UIScreen applicationFrame] ,
Status bar frame and
Keyboard frame are now interface-oriented.
(cf. WWDC2014 video - view controller advancements in iOS8 @ 50:41)

In our case.
Force to rotate with view's transform caused that problem.
We removed that code, rotate with

+ (void)attemptRotationToDeviceOrientation 

and problem solved.

We called that method at our forceRotate method.

-(void)forceRotateLandscape {
    ...
    UIViewController *vc = [UIViewController new];
    [topVc presentViewController:vc animated:NO completion:nil];
    [topVc dismissViewControllerAnimated:NO completion:nil];

    supportedOrientations = UIInterfaceOrientationMaskLandscapeRight;
    [UIViewController attemptRotationToDeviceOrientation];
    ...
}

My guess is that whatever view owns the gesture recognizer isn't getting resized during the rotation for one (or more) of the following reasons:

  • It uses auto layout and isn't pinned to its superview
  • It uses springs and struts and doesn't have the correct UIViewAutoresizing mask
  • It lives in a subview that isn't getting resized

If you're using auto layout, try this in your view controller:

- (void)viewDidLayoutSubviews
{
  // For each subview with its own auto layout:
  [self.mySubview layoutSubviews];

  // ...

  [super viewDidLayoutSubviews];
}

Ok, I've found the issue on my side (I'm the bounty giver).

We were probably using some kind of hack in our App to manually handle the rotation of our views, because we were returning 0 to the - (NSUInteger)supportedInterfaceOrientations in our rootViewController .

- (NSUInteger)supportedInterfaceOrientations {
    return 0; // BOOOOOOO, even forbidden by documentation
}

Then we manually managed our internal views by listening to the UIDeviceRotationChanged notification, rotating them views, and asking the statusBar to rotate as well.

Returning something not 0 to this supportedInterfaceOrientations made the "touch" layer rotate along with the rest.
But now we have to make the code evolve to use iOS rotation instead of our hacky layer.

Also, after investigating more, especially on iPad, you have to use a Storyboard-based UIWindow. Using a XIB-based window will result in its dimensions being wrong when the app is launched while in landscape. This leads to a mountain of buggy frames and messes up badly with our layout.

I had the same problem. In iOS7 all worked fine, in iOS8 it was like the "touch-view" was still in portrait.

I just replaced the main xib with a storyboard, no other change (i've tried a lot playing with screen bound and frame without any results).

Just try it out, let me know if it work also for you. Good luck.

I have the same issue with second window in landscape. It refuses to display itself on the full screen and also to receives touch events on the cut part of the screen. The only solution that I found so far is to enable support of the iPhone6/6+ native resolutions by adding required launch screens. If you do not support these resolutions in your app that might be the same problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM