问题
I'm attempting to display a full screen, 16:9, UIViewController
on an external display using AirPlay.
The goal here is to replace AirPlay mirroring with a custom view controller that will span the full size of the external screen.
Everything seems to work great when the screen connects while the iPad is in portrait mode. When it connects in landscape, the UIViewController
shows up sideways on the external display and only fills half the screen.
In order to this I'm adding my UIViewController
to the attached AirPlay UIScreen
.
-(void) screenConnected:(NSNotification * ) notification {
UIScreen * screen = [notification object]; //this should be the airplay display
UIWindow * window = [[UIWindow alloc] initWithFrame:screen.bounds];
[currentWindow setScreen:screen];
UIViewController * controller = [_delegate createControllerForAirplayDisplay:window];
[window setHidden:NO];
[window setRootViewController:controller];
}
This seems to work fine, I see a full screen display on the iPad as well as the AirPlay TV.
Where I'm seeing an issue is when the AirPlay display is connected while the iPad is in landscape mode. When this happens the AirPlay display renders the UIViewController
sideways and in what looks like portrait mode.
Screen connected in portrait:
Screen connected in landscape, content is sideways and only rendered on half the display:
I've attempted rotating the UIWindow
and UIViewController
using CGAffineTransformMakeRotation
, this does fix the orientation but the view is not centered inside the AirPlay display.
Edit
Filed an issue with Apple related to this, rdar://20817189. I will update this if/when I hear back.
回答1:
I found this in the documentation: https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/WindowAndScreenGuide/UsingExternalDisplay/UsingExternalDisplay.html
Important: Be sure that your app sets the status bar orientation correctly. Because the external display can’t read the host device’s accelerometer to respond to changes in orientation, it relies instead on the status bar orientation, as set in your app.
The external UIWindow
take the orientation from current device, in this case landscape orientation.
So, when you set the frame of your rootViewController, for example (0, 0, 1270, 840) the origin is on top-right corner of your Tv.
You have to force UIWindow
in portrait orientation.
I solved this issue with this code on AppDelegate
:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)_window {
if ([UIScreen mainScreen] == _window.screen || !_window) {
return UIInterfaceOrientationMaskAll;
}else {
return UIInterfaceOrientationPortrait;
}
}
回答2:
Having your shouldAutorotateToInterfaceOrientation
method always return YES
should sort it out for you.
回答3:
Airplay windows set to Portrait Mask will never rotate. The default status bar is Portrait so the rotation value is based off this. Here is a code example that works (Assuming you've stored your Airplay UIWindow as self.secondWindow on your AppDelegate when it connects)
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if(window == self.secondWindow){
return UIInterfaceOrientationMaskPortrait;
}
return UIInterfaceOrientationMaskAll;
}
来源:https://stackoverflow.com/questions/30040055/uiviewcontroller-displayed-sideways-on-airplay-screen-when-launched-from-landsca