2015-06-02 28 views
5

Attualmente, qualsiasi app che creo per iPhone/iPad può essere sottoposta a mirroring su Apple TV tramite AirPlay. Tuttavia, anche in modalità orizzontale, occupa solo la parte centrale dello schermo, con il nero sui lati sinistro e destro. Che cosa è tutto da fare per arrivare ad AirPlay a tutto schermo, nel modo in cui hanno fatto app come Real Racing HD?AirPlay per Apple TV Fullscreen

MODIFICA: Per un suggerimento, ho aggiunto tutto il codice che sto usando, e invece di dire al secondo Windows di usare lo stesso controller di visualizzazione radice normalmente, ho impostato un nuovo VC con un colore diverso per vedere se la meccanica sono stati installati correttamente NON sono, come fa ancora il normale mirroring, anche quando gli dicono di usare un VC diverso.

Ecco AppDelegate.h

#import <UIKit/UIKit.h> 
@class MainView; 
@class ViewController; 
@interface AppDelegate : UIResponder <UIApplicationDelegate> { 
    UIWindow *window; 
    UINavigationController *tabBarController; 

} 

@property (nonatomic, retain) IBOutlet UIWindow *window; 
@property (nonatomic, retain) IBOutlet UINavigationController *tabBarController; 
@property (nonatomic, retain) UIWindow *secondWindow; 
@end 

e parti rilevanti della AppDelegate.m

- (void)checkForExistingScreenAndInitializeIfPresent { 
    if ([[UIScreen screens] count] > 1) { 
     // Get the screen object that represents the external display. 
     UIScreen *secondScreen = [[UIScreen screens] objectAtIndex:1]; 
     // Get the screen's bounds so that you can create a window of the correct size. 
     CGRect screenBounds = secondScreen.bounds; 

     self.secondWindow = [[UIWindow alloc] initWithFrame:screenBounds]; 
     self.secondWindow.screen = secondScreen; 

     // Set up initial content to display... 
     NSLog(@"Setting up second screen: %@", secondScreen); 
     ViewController *mainView = [[ViewController alloc] init]; 
     self.secondWindow.rootViewController = mainView; 
     [self.secondWindow makeKeyAndVisible]; 

     // Show the window. 
     //  self.secondWindow.hidden = NO; 
    } 
    NSLog(@"Screen count too low"); 
} 

- (void)setUpScreenConnectionNotificationHandlers { 
    NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 

    [center addObserver:self selector:@selector(handleScreenDidConnectNotification:) 
        name:UIScreenDidConnectNotification object:nil]; 
    [center addObserver:self selector:@selector(handleScreenDidDisconnectNotification:) 
        name:UIScreenDidDisconnectNotification object:nil]; 
} 

- (void)handleScreenDidConnectNotification:(NSNotification*)aNotification { 
    UIScreen *newScreen = [aNotification object]; 
    CGRect screenBounds = newScreen.bounds; 

    if (!self.secondWindow) { 
     NSLog(@"Initializing secondWindow/screen in notification"); 
     self.secondWindow = [[UIWindow alloc] initWithFrame:screenBounds]; 
     self.secondWindow.screen = newScreen; 

     // Set the initial UI for the window. 
     ViewController *mainView = [[ViewController alloc] init]; 
     self.secondWindow.rootViewController = mainView; 
    } else { 
     NSLog(@"Second window already initialized."); 
    } 
} 

- (void)handleScreenDidDisconnectNotification:(NSNotification*)aNotification { 
    if (self.secondWindow) { 
     // Hide and then delete the window. 
     self.secondWindow.hidden = YES; 
     self.secondWindow = nil; 
    } 
} 
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
[window setRootViewController:tabBarController]; 
    [self setUpScreenConnectionNotificationHandlers]; 
    [self checkForExistingScreenAndInitializeIfPresent]; 
return YES; 
} 
+0

Il sistema operativo deve pensare la vostra applicazione è ancora in modalità verticale. – StilesCrisis

+0

@StilesCrisis no, questo è il comportamento per qualsiasi app, indipendentemente dal fatto che sia in orizzontale, mostrerà una visualizzazione in scala centrata. So che è possibile farlo andare a schermo intero su Apple TV, ma non so come. – user717452

risposta

3

Che cosa tutto è coinvolto con ottenere a airplay a tutto schermo ...

Se vuoi immergerti direttamente, ecco dove inizi a conoscere Windows e Screen s nel mondo iOS: https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/WindowAndScreenGuide/UsingExternalDisplay/UsingExternalDisplay.html

Se si vuole prendere una visione più ampia prima, ecco la pagina di aggregazione con video e altri tutorial/documentazione:

https://developer.apple.com/airplay/

[EDIT] Ecco un estratto di codice da una mia app in cui sto impostando il secondo display. Ho preso molto di questo dai link che ti ho dato. NOTA: "principale" è il dispositivo e "remoto" è per il televisore.

NOTA: questo codice non è completo alla produzione; ci sono ancora cambiamenti di stato a cui non risponde. Connettiti ad un AirPlay Receiver e attiva Mirroring prima di eseguirlo.

ho questo:

@interface AppDelegate() { 
    SFCManagerMainViewController *_mainVC; 
    SFCRemoteMonitorViewController *_remoteVC; 
} 

@end 

L'intestazione:

@property (strong, nonatomic) UIWindow *window; 
@property (strong, nonatomic) UIWindow *secondWindow; 

e questo:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
// Override point for customization after application launch. 

[self setUpScreenConnectionNotificationHandlers]; 
[self checkForExistingScreenAndInitializeIfPresent]; 

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
_mainVC = [[SFCManagerMainViewController alloc] initWithNibName:nil bundle:nil]; 
self.window.rootViewController = _mainVC; 
[self.window makeKeyAndVisible]; 
return YES; 
} 

- (void)checkForExistingScreenAndInitializeIfPresent { 
    if ([[UIScreen screens] count] > 1) { 
     // Get the screen object that represents the external display. 
     UIScreen *secondScreen = [[UIScreen screens] objectAtIndex:1]; 
     // Get the screen's bounds so that you can create a window of the correct size. 
     CGRect screenBounds = secondScreen.bounds; 

     self.secondWindow = [[UIWindow alloc] initWithFrame:screenBounds]; 
     self.secondWindow.screen = secondScreen; 

     // Set up initial content to display... 
     NSLog(@"Setting up second screen: %@", secondScreen); 
     _remoteVC = [[SFCRemoteMonitorViewController alloc] initWithNibName:nil bundle:nil]; 
     self.secondWindow.rootViewController = _remoteVC; 
     [self.secondWindow makeKeyAndVisible]; 

     // Show the window. 
     self.secondWindow.hidden = NO; 
    } 
} 

- (void)setUpScreenConnectionNotificationHandlers { 
    NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 

    [center addObserver:self selector:@selector(handleScreenDidConnectNotification:) 
        name:UIScreenDidConnectNotification object:nil]; 
    [center addObserver:self selector:@selector(handleScreenDidDisconnectNotification:) 
        name:UIScreenDidDisconnectNotification object:nil]; 
} 

- (void)handleScreenDidConnectNotification:(NSNotification*)aNotification { 
    UIScreen *newScreen = [aNotification object]; 
    CGRect screenBounds = newScreen.bounds; 

    if (!self.secondWindow) { 
     NSLog(@"Initializing secondWindow/screen in notification"); 
     self.secondWindow = [[UIWindow alloc] initWithFrame:screenBounds]; 
     self.secondWindow.screen = newScreen; 

     // Set the initial UI for the window. 
     _remoteVC = [[SFCRemoteMonitorViewController alloc] initWithNibName:nil bundle:nil]; 
     self.secondWindow.rootViewController = _remoteVC; 
    } else { 
     NSLog(@"Second window already initialized."); 
    } 
} 

- (void)handleScreenDidDisconnectNotification:(NSNotification*)aNotification { 
    if (self.secondWindow) { 
     // Hide and then delete the window. 
     self.secondWindow.hidden = YES; 
     self.secondWindow = nil; 
    } 
} 
+0

Ho seguito esattamente le istruzioni dal primo collegamento e ho ottenuto uno schermo vuoto sulla mia Apple TV. – user717452

+0

Questo è parte di quello che mi aspetterei. Nel primo collegamento, si ottiene uno schermo aggiuntivo (simile a un secondo monitor, non una duplicazione del monitor esistente) che è il punto in cui si inserisce il contenuto che può essere ridimensionato a tutta larghezza/altezza. Se la tua interfaccia utilizza le classi di dimensione/autolayout, dovresti essere in grado di aggiungere il tuo controller di visualizzazione al secondo schermo e vedere di più di ciò che ti aspetti. –

+0

OK, quindi, seguendo le istruzioni di Apple e aggiungendo ESATTAMENTE il codice che hanno elencato nel link, come faccio a DUPLICARE ciò che è presente sullo schermo del mio iPad sul secondo schermo? – user717452

0

In primo luogo, è possibile che la stessa TV è sovrascrivendo alcune impostazioni overscan?

Ci sono alcune API per UIScreen che si consiglia di controllare, in particolare:

@property(nonatomic) UIScreenOverscanCompensation overscanCompensation 
@property(nonatomic,retain) UIScreenMode *currentMode 
@property(nonatomic,readonly,copy) NSArray *availableModes 

In caso contrario, l'altra opzione è quella di disabilitare il mirroring e fare il disegno in una vista che è la dimensione dello schermo :

//Be sure to check for the screen's existence first :) 
UIScreen *secondScreen = [UIScreen screens][1]; 

//Create a window that is the size of the second screen 
self.externalWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, secondScreen.bounds.size.width, secondScreen.bounds.size.height)]; 

//Set to a view controller that should be displayed 
self.externalWindow.rootViewController = [[MyViewController alloc] init]; 

//Move the new window to the second screen 
self.externalWindow.screen = secondScreen; 
self.externalWindow.hidden = NO; 
+1

Se non aggiungo alcun codice, esso si riflette su Apple TV ma con barre sul lato sinistro e destro. Se aggiungo il codice, ottengo uno schermo vuoto. – user717452

1

Hai solo bisogno di impostare la compensazione overscan:

UIScreen* secondScreen = (...); 
secondScreen.overscanCompensation = UIScreenOverscanCompensationInsetApplicationFrame; 

Se si vuole il codice completo per testare, basta inserire il seguente codice da qualche parte nel vostro AppDelegate.m e application:didFinishLaunchingWithOptions: chiamata [self setupAirplay];

-(void)setupAirplay{ 
    // self.windows is a NSMutableArray property on AppDelegate 
    self.windows = [[NSMutableArray alloc] init]; 

    NSArray* screens = [UIScreen screens]; 
    for (UIScreen *_screen in screens){ 
     if (_screen == [UIScreen mainScreen]) 
      continue; 

     NSNotification* notification = [[NSNotification alloc] initWithName:UIScreenDidConnectNotification object:_screen userInfo:nil]; 
     [self screenDidConnect:notification]; 
    } 

    // Register for notifications 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(screenDidConnect:) 
               name:UIScreenDidConnectNotification 
               object:nil]; 

    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(screenDidDisconnect:) 
               name:UIScreenDidDisconnectNotification 
               object:nil]; 
} 

- (UIWindow *) createWindowForScreen:(UIScreen *)screen { 
    UIWindow *aWindow = nil; 

    // Do we already have a window for this screen? 
    for (UIWindow *window in self.windows){ 
     if (window.screen == screen){ 
      aWindow = window; 
     } 
    } 
    // Still nil? Create a new one. 
    if (aWindow == nil){ 
     aWindow = [[UIWindow alloc] initWithFrame:[screen bounds]]; 
     [aWindow setScreen:screen]; 
     [self.windows addObject:aWindow]; 
    } 

    return aWindow; 
} 

- (void) screenDidConnect:(NSNotification *) notification { 

    UIScreen* screen = [notification object]; 
    NSLog(@"Screen connected: %.0f x %.0f", screen.bounds.size.width, screen.bounds.size.height); 

    // Create a view controller for the new window (you should use a Storyboard/XIB) 
    UIViewController* airplay = [[UIViewController alloc] init]; 
    airplay.view = [[UIView alloc] initWithFrame:screen.bounds]; 
    [airplay.view setBackgroundColor:[UIColor whiteColor]]; 

    UILabel* label = [[UILabel alloc] initWithFrame:screen.bounds]; 
    [label setTextAlignment:NSTextAlignmentCenter]; 
    [label setFont:[UIFont systemFontOfSize:40.0f]]; 
    [label setText:@"AirPlay Screen"]; 

    [airplay.view addSubview:label]; 

    // Comment this line and you'll get the four black borders: 
    screen.overscanCompensation = UIScreenOverscanCompensationInsetApplicationFrame; 

    UIWindow* aWindow = [self createWindowForScreen:screen]; 

    // Add the view controller to the window 
    [aWindow setRootViewController:airplay]; 
    [aWindow setHidden:NO]; 
} 

- (void) screenDidDisconnect:(NSNotification *) notification { 

    NSLog(@"Screen disconnected"); 
    UIScreen* screen = [notification object]; 

    // Find any window attached to this screen, remove it from our window list 
    for (UIWindow *oneWindow in self.windows){ 
     if (oneWindow.screen == screen){ 
      NSUInteger windowIndex = [self.windows indexOfObject:oneWindow]; 
      [self.windows removeObjectAtIndex:windowIndex]; 
     } 
    } 
    return; 
} 

Non ho fatto una risoluzione di 1080p a mio Apple TV terza generazione, mentre il test con il mio iPad Mini 2, ma ho ottenuto una risoluzione di 720p a schermo intero. Non sono sicuro se questo è ciò che ci si aspetta da tutto il concept AirPlay o se qualcosa qui non è abbastanza veloce, ma vorrei poter ottenere 1080p.

Fammi sapere se hai bisogno di ulteriore aiuto per impostare AirPlay, ma dovrebbe funzionare così com'è.

+0

Questo funziona per aggiungere una vista diversa da mostrare sul dispositivo AirPlay, ma voglio semplicemente rispecchiare ciò che è nella mia app su Apple TV. – user717452

+0

Se non aggiungo alcun codice, esso si riflette su Apple TV ma con barre sul lato sinistro e destro. Se aggiungo il codice, ottengo uno schermo vuoto. – user717452

+0

Oh, capisco. Hai provato a impostare la compensazione overscan sulla schermata principale, quindi? (Non sono a casa ora, quindi non posso verificarlo) –

0

Questo funziona per me sia sul vecchio che sul nuovo Apple TV con un iPad Air. La seconda finestra viene visualizzata a schermo intero sul televisore mentre l'interfaccia utente normale viene visualizzata sull'iPad.

Inserire nel vostro AppDelegate.m:

@property UIWindow *secondWindow; 

...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 

    if ([UIScreen screens].count > 1) { 
    [self setUpSecondWindowForScreen:[UIScreen screens][1]]; 
    } 

    NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 
    [center addObserver:self selector:@selector(handleScreenDidConnectNotification:) 
       name:UIScreenDidConnectNotification object:nil]; 
    [center addObserver:self selector:@selector(handleScreenDidDisconnectNotification:) 
       name:UIScreenDidDisconnectNotification object:nil]; 

    return YES; 
} 

- (void)handleScreenDidConnectNotification:(NSNotification*)notification { 
    if (!self.secondWindow) { 
    [self setUpSecondWindowForScreen:[notification object]]; 
    } 
} 

- (void)handleScreenDidDisconnectNotification:(NSNotification*)notification { 
    if (self.secondWindow) { 
    self.secondWindow = nil; 
    } 
} 

- (void)setUpSecondWindowForScreen:(UIScreen*)screen { 
    self.secondWindow = [[UIWindow alloc] init]; 
    self.secondWindow.screen = screen; 
    self.secondWindow.screen.overscanCompensation = UIScreenOverscanCompensationNone; 

    UIViewController *viewController = [[UIViewController alloc] init]; 
    viewController.view.backgroundColor = [UIColor redColor]; 
    self.secondWindow.rootViewController = viewController; 

    [self.secondWindow makeKeyAndVisible]; 
} 

Codice ispirato: https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/WindowAndScreenGuide/UsingExternalDisplay/UsingExternalDisplay.html

Problemi correlati