Come forzare l'orientamento del controller di visualizzazione in iOS 8?


149

Prima iOS 8, abbiamo usato qui sotto code unitamente supportedInterfaceOrientations e shouldAutoRotate metodi delegato di forzare orientamento all'applicazione di qualsiasi orientamento particolare. Ho usato lo snippet di codice qui sotto per ruotare l'app a livello di programmazione sull'orientamento desiderato. In primo luogo, sto cambiando l'orientamento della barra di stato. Quindi, la semplice presentazione e il rifiuto immediato di una vista modale fa ruotare la vista sull'orientamento desiderato.

[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];
UIViewController *c = [[UIViewController alloc]init];
[self presentViewController:vc animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];

Ma questo non funziona in iOS 8. Inoltre, ho visto alcune risposte in overflow dello stack in cui le persone hanno suggerito che dovremmo sempre evitare questo approccio da iOS 8 in poi.

Per essere più specifici, la mia applicazione è un tipo universale di applicazione. Ci sono tre controller in totale.

  1. Controller First View : dovrebbe supportare tutti gli orientamenti in iPad e solo il ritratto (pulsante Home in basso) in iPhone.

  2. Controller Second View - Dovrebbe supportare solo il panorama in tutte le condizioni

  3. Controller per la terza vista - Dovrebbe supportare solo il panorama in tutte le condizioni

Stiamo usando il controller di navigazione per la navigazione della pagina. Dal primo controller di visualizzazione, facendo clic sul pulsante, spingiamo il secondo in pila. Quindi, quando arriva il secondo controller di visualizzazione, indipendentemente dall'orientamento del dispositivo, l'app dovrebbe bloccarsi solo in orizzontale.

Di seguito sono riportati i metodi my shouldAutorotatee supportedInterfaceOrientationsin controller di seconda e terza vista.

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscapeRight;
}

-(BOOL)shouldAutorotate {
    return NO;
}

Esiste una soluzione per questo o un modo migliore di bloccare un controller di visualizzazione con un orientamento particolare per iOS 8. Per favore aiutatemi !!


L'implementazione dei metodi che hai citato nel VC presentato dovrebbe generalmente funzionare (almeno questa è la mia esperienza in iOS 8). Forse la tua configurazione specifica sta causando problemi?
Vladimir Gritsenko,

Forse posso rendere la domanda un po 'più chiara. Modificherò leggermente la domanda.
Rashmi Ranjan Mallick,

@VladimirGritsenko: controlla ora. L'ho modificato.
Rashmi Ranjan Mallick,

Il codice nella domanda non utilizza lo stack del controller di navigazione, ma piuttosto la presentazione modale, quindi non è ancora chiaro cosa stai facendo esattamente. Dirò che nel nostro codice, restituendo SÌ da shouldAutoRotate e restituendo gli orientamenti desiderati da supportInterfaceOrientations nel VC presentato orienta correttamente quel VC.
Vladimir Gritsenko,

Bene, non è proprio un fallimento, è solo un grande cambiamento nel concetto. Che si tratti di un buon cambiamento è un altro argomento.
Kegluneq,

Risposte:


315

Per iOS 7 - 10:

Objective-C:

[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeLeft) forKey:@"orientation"];
[UINavigationController attemptRotationToDeviceOrientation];

Swift 3:

let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
UINavigationController.attemptRotationToDeviceOrientation()

Basta chiamarlo nel - viewDidAppear:controller di visualizzazione presentato.


61
Questa non è un'API privata. Questo è un utilizzo non sicuro delle API. Non stai usando alcun metodo privato, ma usando "cose ​​interne". Se Apple cambia il valore di "orientamento", fallisce. Peggio ancora: se Apple cambia il significato del valore "orientamento", non sai cosa stai cambiando impostando il valore.
Sonxurxo,

4
Per l'animazione disabilitare, messo [UIView setAnimationsEnabled:NO];in viewWillAppeare [UIView setAnimationsEnabled:YES];in viewDidAppear, in relazione: stackoverflow.com/a/6292506/88597
ohho

3
Bello hack, ma il problema è che non sta eseguendo didRotateFromInterfaceOrientation dopo aver impostato il nuovo valore di orientamento (sospiro)
loretoparisi,

2
In iOS 9.2, questo cambia solo l'orientamento ma non il blocco.
Mark13426,

2
Per tutti coloro che si comportano bene il 90% delle volte e buggy l'altro 10% delle volte, chiamare questo dopo aver impostato il tasto di orientamento:[UINavigationController attemptRotationToDeviceOrientation];
Albert Renshaw

93

La rotazione dell'orientamento è un po 'più complicata se ci si trova all'interno di un UINavigationControllero UITabBarController. Il problema è che se un controller di visualizzazione è incorporato in uno di questi controller, il controller di navigazione o della barra delle schede ha la precedenza e prende le decisioni sull'autorotazione e sugli orientamenti supportati.

Uso le seguenti 2 estensioni su UINavigationController e UITabBarController in modo che i controller di visualizzazione incorporati in uno di questi controller possano prendere le decisioni.

Dai potenza ai controller di visualizzazione!

Swift 2.3

extension UINavigationController {
    public override func supportedInterfaceOrientations() -> Int {
        return visibleViewController.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        return visibleViewController.shouldAutorotate()
    }
}

extension UITabBarController {
    public override func supportedInterfaceOrientations() -> Int {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations()
        }
        return super.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate()
        }
        return super.shouldAutorotate()
    }
}

Swift 3

extension UINavigationController {
    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return visibleViewController?.supportedInterfaceOrientations ?? super.supportedInterfaceOrientations
    }

    open override var shouldAutorotate: Bool {
        return visibleViewController?.shouldAutorotate ?? super.shouldAutorotate
    }
}

extension UITabBarController {
    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations
        }
        return super.supportedInterfaceOrientations
    }

    open override var shouldAutorotate: Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate
        }
        return super.shouldAutorotate
    }
}

Ora puoi sovrascrivere il supportedInterfaceOrientationsmetodo o puoi eseguire l'override shouldAutoRotatenel controller di visualizzazione che desideri bloccare, altrimenti puoi escludere le sostituzioni in altri controller di visualizzazione che desideri ereditare il comportamento di orientamento predefinito specificato nel plist della tua app

Disabilita rotazione

class ViewController: UIViewController {
    override func shouldAutorotate() -> Bool {
        return false
    }
}

Blocca in orientamento specifico

class ViewController: UIViewController {
    override func supportedInterfaceOrientations() -> Int {
        return Int(UIInterfaceOrientationMask.Landscape.rawValue)
    }
}

In teoria questo dovrebbe funzionare per tutte le gerarchie complesse di controller di visualizzazione, ma ho notato un problema con UITabBarController. Per qualche motivo vuole usare un valore di orientamento predefinito. Vedere il seguente post di blog se si è interessati a imparare a risolvere alcuni dei problemi:

Rotazione schermo di blocco


1
So che questo è un post molto vecchio, ma dove metteresti il ​​codice di estensione?
dwinnbrown,

7
La marcatura verso il basso per uno Swift risponde solo a una domanda dell'obiettivo-C.
Charlie Scott-Skinner,

17
Questa è una buona soluzione per Swift e ObjC. Non capisco perché le persone non votano. Hai avuto l'idea e quindi scrivere il codice è facile. Perché lamentarsi?
Zhao,

2
@Krodak, nelle estensioni prova a cambiare "-> Int" in "-> UIInterfaceOrientationMask". Ha fatto il trucco per me.
the_pantless_coder

2
L'idea e il codice sono perfetti, lo adoro, ma c'è un problema quando si usa UINavigationController e si torna da un UIViewController in orizzontale a uno che deve essere visualizzato in verticale. Qualche idea?
crisiGriega,

24

Questo è ciò che ha funzionato per me:

https://developer.apple.com/library//ios/documentation/UIKit/Reference/UIViewController_Class/index.html#//apple_ref/occ/clm/UIViewController/attemptRotationToDeviceOrientation

Chiamalo nel tuo viewDidAppear: metodo.

- (void) viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    [UIViewController attemptRotationToDeviceOrientation];
}

3
Molto utile, se il dispositivo è già ruotato e devi ruotare il controller della vista
avdyushin

2
Bella risposta. Se utilizzato in combinazione con la risposta accettata, questo funziona bene per me ogni volta in Swift e iOS 9+.
AndyDunn,

1
Anche se penso che non sia la risposta alla domanda posta, ma mi ha davvero aiutato.
Abdurrahman Mubeen Ali,

21

Ho scoperto che se si tratta di un controller di visualizzazione presentato, è possibile eseguire l'override preferredInterfaceOrientationForPresentation

Swift:

override func supportedInterfaceOrientations() -> Int {
  return Int(UIInterfaceOrientationMask.Landscape.rawValue)
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
  return UIInterfaceOrientation.LandscapeLeft
}

override func shouldAutorotate() -> Bool {
  return false
}

4
Sembra che la risposta accettata inneschi semplicemente un cambiamento di orientamento in orizzontale. Quello che hai mostrato qui è come forzare un controller di visualizzazione ad essere solo in orizzontale e non influire sul controller di visualizzazione di presentazione (che è esattamente quello di cui ho bisogno). Grazie.
Clifton Labrum,

1
@CliftonLabrum hai fatto altro per forzare solo il paesaggio? Utilizzando lo stesso codice, il controller di visualizzazione è ancora in grado di ruotare con un altro orientamento.
Crashalot,

In seguito ho capito che hai ragione. Non ho ancora trovato una soluzione.
Clifton Labrum,

1
Questo ha funzionato per me. Sono stato in grado di mantenere un singolo controller di visualizzazione in modalità Ritratto usando questo codice (sostituendo Orizzontale con Ritratto). +1
Mark Barrasso,

Sì! Questo ha funzionato anche per me in Xcode 7.3 e Swift 2.2. Ma è ancora necessario definire l'applicazione func per supportInterfaceOrientationsForWindow in AppDelegate.
charles.cc.hsu,

16

In questo modo funziona per me in Swift 2 iOS 8.x:

PS (questo metodo non richiede di sovrascrivere le funzioni di orientamento come dovrebbe automatizzare su ogni viewController, solo un metodo su AppDelegate)

Controllare "richiede schermo intero" nelle informazioni generali del progetto. inserisci qui la descrizione dell'immagine

Quindi, su AppDelegate.swift crea una variabile:

var enableAllOrientation = false

Quindi, metti anche questa funzione:

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
        if (enableAllOrientation == true){
            return UIInterfaceOrientationMask.All
        }
        return UIInterfaceOrientationMask.Portrait
}

Quindi, in ogni classe del tuo progetto puoi impostare questa var in viewWillAppear:

override func viewWillAppear(animated: Bool)
{
        super.viewWillAppear(animated)
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        appDelegate.enableAllOrientation = true
}

Se devi fare una scelta in base al tipo di dispositivo puoi farlo:

override func viewWillAppear(animated: Bool)
    {
        super.viewWillAppear(animated)
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        switch UIDevice.currentDevice().userInterfaceIdiom {
        case .Phone:
        // It's an iPhone
           print(" - Only portrait mode to iPhone")
           appDelegate.enableAllOrientation = false
        case .Pad:
        // It's an iPad
           print(" - All orientation mode enabled on iPad")
           appDelegate.enableAllOrientation = true
        case .Unspecified:
        // Uh, oh! What could it be?
           appDelegate.enableAllOrientation = false
        }
    }

spiegazione molto bella
Mihir Oza,

11

Prima di tutto: questa è una cattiva idea, in generale, qualcosa di sbagliato nell'architettura della tua app, ma, in sh..t happenstal caso, puoi provare a creare qualcosa di simile di seguito:

final class OrientationController {

    static private (set) var allowedOrientation:UIInterfaceOrientationMask = [.all]

    // MARK: - Public

    class func lockOrientation(_ orientationIdiom: UIInterfaceOrientationMask) {
        OrientationController.allowedOrientation = [orientationIdiom]
    }

    class func forceLockOrientation(_ orientation: UIInterfaceOrientation) {
        var mask:UIInterfaceOrientationMask = []
        switch orientation {
            case .unknown:
                mask = [.all]
            case .portrait:
                mask = [.portrait]
            case .portraitUpsideDown:
                mask = [.portraitUpsideDown]
            case .landscapeLeft:
                mask = [.landscapeLeft]
            case .landscapeRight:
                mask = [.landscapeRight]
        }

        OrientationController.lockOrientation(mask)

        UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
    }
}

Di, in AppDelegate

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // do stuff
    OrientationController.lockOrientation(.portrait)
    return true
}

// MARK: - Orientation

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return OrientationController.allowedOrientation
}

E ogni volta che vuoi cambiare orientamento fai come:

OrientationController.forceLockOrientation(.landscapeRight)

Nota: a volte, il dispositivo potrebbe non aggiornarsi da tale chiamata, quindi potrebbe essere necessario eseguire le seguenti operazioni

OrientationController.forceLockOrientation(.portrait)
OrientationController.forceLockOrientation(.landscapeRight)

È tutto


9

Questo dovrebbe funzionare da iOS 6 in poi, ma l'ho testato solo su iOS 8. Sottoclasse UINavigationControllere sovrascrive i seguenti metodi:

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationLandscapeRight;
}

- (BOOL)shouldAutorotate {
    return NO;
}

Oppure chiedi al controller di visualizzazione visibile

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return self.visibleViewController.preferredInterfaceOrientationForPresentation;
}

- (BOOL)shouldAutorotate {
    return self.visibleViewController.shouldAutorotate;
}

e implementare i metodi lì.


Ho appena provato questo sulla mia app in Xcode 8.2.1 con iOS 10.0 e funziona. Il mio menu di gioco è la prima schermata e non ruota; tutte le altre viste ruotano. Perfetto! Ne ho dato uno. Avevo solo bisogno della funzione "favoriteInterfaceOrientationForPresentation" fornita da Mojo66.
Philip Borges,

9

Questo è un feedback ai commenti nella risposta di Sid Shah , riguardo a come disabilitare le animazioni usando:

[UIView setAnimationsEnabled:enabled];

Codice:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:NO];
    [UIView setAnimationsEnabled:NO];

    // Stackoverflow #26357162 to force orientation
    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:NO];
    [UIView setAnimationsEnabled:YES];
}

Come posso usarlo per Portrait.
Muju,

6

Se stai usando navigationViewController devi creare la tua superclasse per questo e sovrascrivere:

- (BOOL)shouldAutorotate {
  id currentViewController = self.topViewController;

  if ([currentViewController isKindOfClass:[SecondViewController class]])
    return NO;

  return YES;
}

questo disabiliterà la rotazione in SecondViewController ma se si preme SecondViewController quando il dispositivo è orientato in verticale , SecondViewController apparirà in modalità verticale .

Supponi di utilizzare lo storyboard. Devi creare segue manuale ( How to ) e nel tuo metodo "onClick":

- (IBAction)onPlayButtonClicked:(UIBarButtonItem *)sender {
  NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
  [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
  [self performSegueWithIdentifier:@"PushPlayerViewController" sender:self];
}

Ciò forzerà l'orientamento orizzontale prima che la superclasse disabiliti la funzione di rotazione automatica.


6

Sui Xcode 8metodi vengono convertiti in proprietà, quindi il seguente funziona con Swift:

override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.portrait
}

override public var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return UIInterfaceOrientation.portrait
}

override public var shouldAutorotate: Bool {
    return true
}

Questo blocca l'orientamento?
bnussey,

1
@bnussey Volevo impedire la rotazione automatica ed essere sempre in portraitmodalità indipendentemente dall'orientamento su iPad, con il shouldAutorotateritorno vero l'ho raggiunto.
Ali Momen Sani,

4

Ho provato molte soluzioni, ma quella che ha funzionato è la seguente:

Non è necessario modificare info.plistin ios 8 e 9.

- (BOOL) shouldAutorotate {
    return NO;
}   

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return (UIInterfaceOrientationPortrait | UIInterfaceOrientationPortraitUpsideDown);
}

Possibili orientamenti dalla documentazione Apple :

UIInterfaceOrientationUnknown

L'orientamento del dispositivo non può essere determinato.

UIInterfaceOrientationPortrait

Il dispositivo è in modalità verticale, con il dispositivo tenuto in posizione verticale e il pulsante Home in basso.

UIInterfaceOrientationPortraitUpsideDown

Il dispositivo è in modalità verticale ma capovolto, con il dispositivo tenuto in posizione verticale e il pulsante Home in alto.

UIInterfaceOrientationLandscapeLeft

Il dispositivo è in modalità orizzontale, con il dispositivo tenuto in posizione verticale e il pulsante Home sul lato sinistro.

UIInterfaceOrientationLandscapeRight

Il dispositivo è in modalità orizzontale, con il dispositivo tenuto in posizione verticale e il pulsante Home sul lato destro.


3

La combinazione di risposte Sids e Koreys ha funzionato per me.

Estensione del controller di navigazione:

extension UINavigationController {
    public override func shouldAutorotate() -> Bool {
        return visibleViewController.shouldAutorotate()
    }
}

Quindi disabilitando la rotazione sulla vista singola

class ViewController: UIViewController {
    override func shouldAutorotate() -> Bool {
        return false
    }
}

E ruotando verso l'orientamento appropriato prima del seguito

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if (segue.identifier == "SomeSegue")
    {
        let value = UIInterfaceOrientation.Portrait.rawValue;
        UIDevice.currentDevice().setValue(value, forKey: "orientation")
    }
}

Sai se questo potrebbe aiutare il mio problema in cui il controller di visualizzazione visualizzato è in orizzontale per un secondo prima che ruoti in verticale come dovrebbe sempre essere? domanda è qui: stackoverflow.com/questions/30693964/...
dwinnbrown

3

La soluzione migliore sopra:

let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")

non ha funzionato per me quando l'ho chiamato in viewDidAppear del controller di visualizzazione presentato. Tuttavia ha funzionato quando l'ho chiamato in preparForSegue nel controller della vista di presentazione.

(Siamo spiacenti, non abbastanza punti reputazione per commentare quella soluzione, quindi ho dovuto aggiungerlo in questo modo)


Ho funzionato, ma quando si passa da un controller di visualizzazione orizzontale a un controller di visualizzazione verticale, il controller di visualizzazione che dovrebbe mostrare in verticale viene brevemente mostrato in orizzontale prima di ruotare da solo. se qualcuno sa come aiutare la mia domanda è qui: stackoverflow.com/questions/30693964/...
dwinnbrown

@dwinnbrown at viewDidAppear il controller di visualizzazione è già visibile. Forse provi invece da viewDidLoad?
Crashalot,

@Crashalot Ora ho risolto questo problema. Si prega di vedere la risposta che ho contrassegnato come corretta.
dwinnbrown,

@dwinnbrown il link alla tua domanda è morto. aggiornare? Grazie!
Crashalot,

@Crashalot la community l'ha cancellato ma ho votato per ripristinarlo. Ti farò sapere presto
dwinnbrown,

3

[iOS9 +] Se qualcuno trascina fino in fondo perché nessuna delle soluzioni precedenti ha funzionato e se si presenta la vista che si desidera modificare l'orientamento di seguito, è possibile che si desideri verificare questo.

Controlla il tipo di presentazione del tuo seguito. Il mio era "nel contesto attuale". Quando l'ho cambiato a schermo intero, ha funzionato.

Grazie a @GabLeRoux, ho trovato questa soluzione.

  • Questa modifica funziona solo se combinata con le soluzioni sopra.

2

Le mie esigenze sono

  1. blocca tutte le viste in modalità verticale
  2. utilizzare AVPlayerViewControllerper riprodurre video

Durante la riproduzione del video, se si tratta di un paesaggio, consentire allo schermo di ruotare il paesaggio verso destra e il paesaggio verso sinistra. Se è un ritratto, blocca la vista solo in modalità ritratto.

Innanzitutto, definire supportedInterfaceOrientationsForWindowinAppDelegate.swift

var portrait = true
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    if portrait {
        return .Portrait
    } else {
        return .Landscape
    }
}

In secondo luogo, nel controller della vista principale, definire le seguenti funzioni

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    print("\(#function)")
    return .Portrait
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    return .Portrait
}

override func shouldAutorotate() -> Bool {
    return false
}

Quindi, è necessario eseguire la sottoclasse AVPlayerViewController

class MyPlayerViewController: AVPlayerViewController {

    var size: CGSize?

    var supportedOrientationMask: UIInterfaceOrientationMask?
    var preferredOrientation: UIInterfaceOrientation?

    override func viewDidLoad() {
        super.viewDidLoad()

        if let size = size {
            if size.width > size.height {
                self.supportedOrientationMask =[.LandscapeLeft,.LandscapeRight]
                self.preferredOrientation =.LandscapeRight
            } else {
                self.supportedOrientationMask =.Portrait
                self.preferredOrientation =.Portrait
            }
        }
    }

Sostituisci queste tre funzioni in MyPlayerViewController.swift

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return self.supportedOrientationMask!
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    return self.preferredOrientation!
}

Poiché l'utente può ruotare il dispositivo verso sinistra o verso destra, è necessario impostare la rotazione automatica su true

override func shouldAutorotate() -> Bool {
    return true
}

Infine, crea MyPlayerViewControllerun'istanza nel controller della vista e imposta il valore della dimensione della proprietà.

let playerViewController = MyPlayerViewController()

// Get the thumbnail  
let thumbnail = MyAlbumFileManager.sharedManager().getThumbnailFromMyVideoMedia(......)

let size = thumbnail?.size
playerViewController.size = size

Avvia il tuo giocatore con corretto videoUrl, quindi assegnalo a playerViewController. Buona programmazione!


2
- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [UIViewController attemptRotationToDeviceOrientation];
}

1

Sembra che ci sia ancora qualche dibattito sul modo migliore per svolgere questo compito, quindi ho pensato di condividere il mio approccio (funzionante). Aggiungi il seguente codice nella tua UIViewControllerimplementazione:

- (void) viewWillAppear:(BOOL)animated
{
    [UIViewController attemptRotationToDeviceOrientation];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

-(BOOL)shouldAutorotate
{
    return NO;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscapeLeft;
}

Per questo esempio, dovrai anche impostare gli orientamenti del dispositivo consentiti su "Orizzontale a sinistra" nelle impostazioni del tuo progetto (o direttamente in info.plist). Basta cambiare l'orientamento specifico che si desidera forzare se si desidera qualcosa di diversoLandscapeLeft.

La chiave per me era la attemptRotationToDeviceOrientationchiamata viewWillAppear- senza che la vista non ruotasse correttamente senza ruotare fisicamente il dispositivo.


Metodo obsoleto.
Saqib Omer,

1

Secondo la risposta di Korey Hinton

Swift 2.2:

extension UINavigationController {
    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return visibleViewController!.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        return visibleViewController!.shouldAutorotate()
    }
}


extension UITabBarController {
    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations()
        }
        return super.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate()
        }
        return super.shouldAutorotate()
    }
}

Disabilita rotazione

override func shouldAutorotate() -> Bool {
    return false
}

Blocca in orientamento specifico

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.Portrait
}

1

Ho provato alcune soluzioni qui e la cosa importante da capire è che è il controller della vista radice che determinerà se ruoterà o meno.

Ho creato il seguente progetto object -c github.com/GabLeRoux/RotationLockInTabbedViewChild con un esempio funzionante di una TabbedViewControllervista a cui è consentito ruotare una vista figlio e l'altra vista figlio è bloccata in verticale.

Non è perfetto, ma funziona e la stessa idea dovrebbe funzionare per altri tipi di viste di root come NavigationViewController. :)

La vista figlio blocca l'orientamento del genitore


0

Secondo la soluzione mostrata da @ sid-sha devi mettere tutto nel viewDidAppear:metodo, altrimenti non verrai didRotateFromInterfaceOrientation:licenziato, quindi qualcosa del tipo:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
    if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
        interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
        NSNumber *value = [NSNumber numberWithInt:interfaceOrientation];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    }
}

0

La mia soluzione

In AppDelegate:

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    if let topController = UIViewController.topMostViewController() {
        if topController is XXViewController {
            return [.Portrait, .LandscapeLeft]
        }
    }
    return [.Portrait]
}

XXViewController è il ViewController che si desidera supportare la modalità orizzontale.

Quindi la soluzione di Sunny Shah funzionerebbe XXViewControllersu qualsiasi versione di iOS:

let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")

Questa è la funzione di utilità per trovare il massimo ViewController.

extension UIViewController {

    /// Returns the current application's top most view controller.
    public class func topMostViewController() -> UIViewController? {
        let rootViewController = UIApplication.sharedApplication().windows.first?.rootViewController
        return self.topMostViewControllerOfViewController(rootViewController)
    }



    /// Returns the top most view controller from given view controller's stack.
    class func topMostViewControllerOfViewController(viewController: UIViewController?) -> UIViewController? {
        // UITabBarController
        if let tabBarController = viewController as? UITabBarController,
           let selectedViewController = tabBarController.selectedViewController {
            return self.topMostViewControllerOfViewController(selectedViewController)
        }

        // UINavigationController
        if let navigationController = viewController as? UINavigationController,
           let visibleViewController = navigationController.visibleViewController {
            return self.topMostViewControllerOfViewController(visibleViewController)
        }

        // presented view controller
        if let presentedViewController = viewController?.presentedViewController {
            return self.topMostViewControllerOfViewController(presentedViewController)
        }

        // child view controller
        for subview in viewController?.view?.subviews ?? [] {
            if let childViewController = subview.nextResponder() as? UIViewController {
                return self.topMostViewControllerOfViewController(childViewController)
            }
        }

        return viewController
    }

}

0

Utilizzare questo per bloccare l'orientamento del controller di visualizzazione, testato su IOS 9:

// Blocca l'orientamento in orizzontale a destra

-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscapeRight;
}

-(NSUInteger)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController {
    return UIInterfaceOrientationMaskLandscapeRight;
}

0

Ho lo stesso problema e spreco così tanto tempo per questo. Quindi ora ho la mia soluzione. L'impostazione della mia app è solo di supporto verticale, tuttavia, alcune schermate della mia app devono avere solo un orientamento orizzontale. L'ho risolto con una variabile isShouldRotate su AppDelegate . E la funzione di AppDelegate :

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
    if isShouldRotate == true {
        return Int(UIInterfaceOrientationMask.Landscape.rawValue)
    }
    return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}

E infine quando un ViewControllerA necessita di uno stato orizzontale. Basta farlo: prima di push / presente a ViewControllerA assegnare isShouldRotate al vero . Non dimenticare che quando si assegna / ignora l' assegnazione del controller èShouldRotate su false in viewWillDisappear .


0

Per me, il VC di livello superiore doveva implementare le sostituzioni di orientamento. L'uso dei VC in pila non avrà alcun effetto se il VC in alto non sta implementando.

VC-main
    |
    -> VC 2
        |
        -> VC 3

Viene ascoltato solo VC-Main, essenzialmente nei miei test.


0

Sembra che anche tu qui ci siano così tante risposte che nessuno era sufficiente per me. Volevo forzare l'orientamento e poi tornare indietro all'orientamento del dispositivo ma[UIViewController attemptRotationToDeviceOrientation]; non ha funzionato. Ciò che ha anche fatto tutto ciò che è complicato è che ho aggiunto che dovrebbe essere automatico su false in base a una risposta e non è stato possibile ottenere gli effetti desiderati per tornare indietro correttamente in tutti gli scenari.

Quindi questo è quello che ho fatto:

Prima di spingere il controller in chiamata nel suo costruttore init questo:

_userOrientation = UIDevice.currentDevice.orientation;
[UIDevice.currentDevice setValue:@(UIInterfaceOrientationPortrait) forKey:@"orientation"];
[self addNotificationCenterObserver:@selector(rotated:)
                               name:UIDeviceOrientationDidChangeNotification];

Quindi salvo l'ultimo orientamento del dispositivo e mi registro per l'evento di cambio orientamento. L'evento di cambiamento di orientamento è semplice:

- (void)rotated:(NSNotification*)notification {
    _userOrientation = UIDevice.currentDevice.orientation;
}

E in vista del dissenso, mi limito a ritornare a qualsiasi orientamento che ho come utente.

- (void)onViewDismissing {
    super.onViewDismissing;
    [UIDevice.currentDevice setValue:@(_userOrientation) forKey:@"orientation"];
    [UIViewController attemptRotationToDeviceOrientation];
}

E anche questo deve esserci:

- (BOOL)shouldAutorotate {
    return true;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

E anche il controller di navigazione deve delegare a Dovrebbe autorizzare e supportato InterfaceOrientations, ma che la maggior parte delle persone ha già credo.

PS: Scusa se uso alcune estensioni e classi di base, ma i nomi sono abbastanza significativi, quindi il concetto è comprensibile, renderà ancora più estensioni perché non è troppo carino ora.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.