web-dev-qa-db-fra.com

Détecter si l'application est en cours d'exécution en mode glisser sur ou en affichage fractionné sous iOS 9

Dans iOS 9, est-il possible de détecter le moment où une application est en cours d'exécution dans le mode glisser ou afficher en mode fractionné d'iOS 9?

J'ai essayé de lire la documentation d'Apple sur le multitâche iOS 9, mais je n'ai pas eu de chance avec cela…

Je pose la question parce que mon application peut comporter une fonctionnalité que je souhaiterais désactiver lors de son ouverture dans un diaporama.

34
Matias Korhonen

Il suffit de vérifier si votre fenêtre occupe tout l'écran:

BOOL isRunningInFullScreen = CGRectEqualToRect([UIApplication sharedApplication].delegate.window.frame, [UIApplication sharedApplication].delegate.window.screen.bounds);

Si c'est faux, vous exécutez une vue fractionnée ou une diapositive. 

Voici le code snippé qui maintiendra automatiquement ce drapeau indépendamment de la rotation

-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
{
 // simply create a property of 'BOOL' type
 isRunningInFullScreen = CGRectEqualToRect([UIApplication sharedApplication].delegate.window.frame, [UIApplication sharedApplication].delegate.window.screen.bounds);
}
30
Tamás Zahola

Juste un autre moyen de reconditionner tout cela 

extension UIApplication {
    public var isSplitOrSlideOver: Bool {
        guard let w = self.delegate?.window, let window = w else { return false }
        return !window.frame.equalTo(window.screen.bounds)
    }
}

alors vous pouvez juste 

  • UIApplication.shared.isSplitOrSlideOver dans Swift 
  • UIApplication.sharedApplication.isSplitOrSlideOver en Objective-C

Notez que, dans Swift, l’objet window est un double facultatif ... WTF !

14
Dan Rosenstark

Je suis en retard à la fête, mais si vous voulez une propriété qui fonctionne indépendamment de l'orientation, essayez celle-ci:

extension UIApplication 
{
    func isRunningInFullScreen() -> Bool
    {
        if let w = self.keyWindow
        {
            let maxScreenSize = max(UIScreen.mainScreen().bounds.size.width, UIScreen.mainScreen().bounds.size.height)
            let minScreenSize = min(UIScreen.mainScreen().bounds.size.width, UIScreen.mainScreen().bounds.size.height)
            let maxAppSize = max(w.bounds.size.width, w.bounds.size.height)
            let minAppSize = min(w.bounds.size.width, w.bounds.size.height)
            return maxScreenSize == maxAppSize && minScreenSize == minAppSize
        }

        return true
    }
}
9
lars

Vous pouvez regarder à la fois -willTransitionToTraitCollection: withTransitionCoordinator: pour la classe de taille et viewWillTransitionToSize: withTransitionCoordinator: pour la CGSize de votre vue. Le codage en dur dans les valeurs de taille n'est toutefois pas recommandé.

3
stevethomp

J'ai récemment eu à déterminer le style d'affichage d'une application en fonction, notamment, non seulement en cas de changement de vue ou de diaporama, mais également en fonction de la portion d'écran utilisée 2/3). L'ajout de cela à une sous-classe ViewController a permis de résoudre le problème. 

/// Dismisses this ViewController with animation from a modal state.
func dismissFormSheet () {
    dismissViewControllerAnimated(true, completion: nil)
}

private func deviceOrientation () -> UIDeviceOrientation {
    return UIDevice.currentDevice().orientation
}

private func getScreenSize () -> (description:String, size:CGRect) {
    let size = UIScreen.mainScreen().bounds
    let str = "SCREEN SIZE:\nwidth: \(size.width)\nheight: \(size.height)"
    return (str, size)
}

private func getApplicationSize () -> (description:String, size:CGRect) {
    let size = UIApplication.sharedApplication().windows[0].bounds
    let str = "\n\nAPPLICATION SIZE:\nwidth: \(size.width)\nheight: \(size.height)"
    return (str, size)
}


func respondToSizeChange (layoutStyle:LayoutStyle) {
    // Respond accordingly to the change in size.
}

enum LayoutStyle: String {
    case iPadFullscreen         = "iPad Full Screen"
    case iPadHalfScreen         = "iPad 1/2 Screen"
    case iPadTwoThirdScreeen    = "iPad 2/3 Screen"
    case iPadOneThirdScreen     = "iPad 1/3 Screen"
    case iPhoneFullScreen       = "iPhone"
}

private func determineLayout () -> LayoutStyle {
    if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
        return .iPhoneFullScreen
    }
    let screenSize = getScreenSize().size
    let appSize = getApplicationSize().size
    let screenWidth = screenSize.width
    let appWidth = appSize.width
    if screenSize == appSize {
        return .iPadFullscreen
    }

    // Set a range in case there is some mathematical inconsistency or other outside influence that results in the application width being less than exactly 1/3, 1/2 or 2/3.
    let lowRange = screenWidth - 15
    let highRange = screenWidth + 15

    if lowRange / 2 <= appWidth && appWidth <= highRange / 2 {
        return .iPadHalfScreen
    } else if appWidth <= highRange / 3 {
        return .iPadOneThirdScreen
    } else {
        return .iPadTwoThirdScreeen
    }

}

override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    respondToSizeChange(determineLayout())
}
3
Michael Voccola

La classe de taille horizontale sera compacte lorsqu’il s’agit d’une vue fractionnée ou divisée à 33%. Je ne pense pas que vous puissiez détecter une fois que vous atteignez 50% ou 66% cependant. 

2
jrturton

Après beaucoup de "bricolage", j'ai trouvé une solution pour mon application qui pourrait fonctionner pour vous:

Dans AppDelegate.Swift, créez la variable suivante:

var slideOverActive: Bool = false

Ensuite, dans TOUS vos contrôleurs de vue, ajoutez UIApplicationDelegate à la définition de classe, créez une variable appDelegate, puis ajoutez la fonction ci-dessous traitCollectionDidChange:

class myViewController: UIViewController, UIApplicationDelegate {

var appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {

        let screenWidth = UIScreen.mainScreen().bounds.width

        if previousTraitCollection != nil {
            let horizontalSizeClass: Int = previousTraitCollection!.horizontalSizeClass.rawValue

            if screenWidth == 1024 || screenWidth == 768 { // iPad

                if horizontalSizeClass == 2 { // Slide Over is ACTIVE!

                    appDelegate.slideOverActive = true

                } else {

                    appDelegate.slideOverActive = false

                }
            }
        }
    }

}

Ensuite, où que vous souhaitiez vérifier dans votre code si le curseur est actif ou non, vérifiez simplement:

if appDelegate.slideOverActive == true {

    // DO THIS

} else {

    // DO THIS

}

C'est un peu une solution de contournement, mais cela fonctionne pour moi pour le moment.

Bonne route!

1
AT3D

Comme la solution de Dan Rosenstark, mais modifié pour fonctionner sur le nouvel iPad Pro qui semble signaler une hauteur différente de frame et screen.bounds selon qu'il est exécuté directement sur le périphérique via Xcode, ou s'il est compilé et publié via TestFlight Magasin d'applications. La hauteur renverrait 980 par AS ou TF, plutôt que 1024 comme il était supposé aimer par Xcode, ce qui rend impossible de renvoyer true.

extension UIApplication {
    public var isSplitOrSlideOver: Bool {
        guard let w = self.delegate?.window, let window = w else { return false }
        return !(window.frame.width == window.screen.bounds.width)
    }
}
1
eskimo

Essai de [UIScreen mainScreen] .bounds, Self.window.screen.bounds, Self.window.frame, UIApplication.sharedApplication.keyWindow.frame et ainsi de suite, la seule solution opérationnelle était la méthode obsolète

CGRect frame = [UIScreen mainScreen].applicationFrame;

Que j'ai fixé de cette façon

CGRect frame = [UIScreen mainScreen].applicationFrame;
frame = CGRectMake(0, 0, frame.size.width + frame.Origin.x, frame.size.height + frame.Origin.y);
self.window.frame = frame;
0
FunkyKat

J'ai écrit une bibliothèque SizeClasser basée sur la bibliothèque de @Michael Voccola.
Vous pouvez l’initialiser avec la traitCollection de votre contrôleur de vue et détecter les vues fractionnées ainsi que l’orientation spécifique du périphérique.
Ainsi, vous pourriez écrire votre code spécifiquement à 1/3 de la vue divisée horizontale ou à 1/3 de la vue portrait divisée, ce que UITraitCollection ne vous permet pas de détecter.
https://github.com/cemolcay/SizeClasser

0
cem olcay

Ajout à la réponse de @ Tamas:
Voici l'extrait de code qui gérera automatiquement cet indicateur, quelle que soit la rotation.

 -(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
{
 // simply create a property of 'BOOL' type
 isRunningInFullScreen = CGRectEqualToRect([UIApplication sharedApplication].delegate.window.frame, [UIApplication sharedApplication].delegate.window.screen.bounds);
}
0
Sam92

Et je suis vraiment en retard à la fête! Néanmoins, voici une solution simple et rapide au problème. En utilisant let width = UIScreen.mainScreen().applicationFrame.size.width, nous pouvons détecter la largeur de la fenêtre de mon application, puis faire en sorte que des choses se produisent lorsqu'elle est inférieure à un certain nombre (c'est-à-dire sur l'écran de l'iPhone ou en mode fractionné), utile pour créer différentes choses sur des écrans plus petits. Pour que l'ordinateur vérifie la largeur encore et encore, nous pouvons exécuter un NSTimer tous les centièmes de seconde, puis effectuer des opérations si la largeur est supérieure/inférieure à quelque chose.

Quelques mesures pour vous (vous devez décider de la largeur à utiliser pour que les choses se produisent au-dessus/en dessous): IPhone 6S Plus: 414.0mm
iPhone 6S: 375.0mm
iPhone 5S: 320.0mm
iPad (portrait): 768.0mm
iPad (vue divisée 1/3): 320.0mm
iPad Air 2 (vue divisée en deux): 507.0mm
iPad (paysage): 1024.0mm 

Voici un extrait de code:

class ViewController: UIViewController {

var widthtimer = NSTimer()

func checkwidth() {

var width = UIScreen.mainScreen().applicationFrame.size.width

if width < 507 { // The code inside this if statement will occur if the width is below 507.0mm (on portrait iPhones and in iPad 1/3 split view only). Use the measurements provided in the Stack Overflow answer above to determine at what width to have this occur.

    // do the thing that happens in split view
    textlabel.hidden = false

} else if width > 506 {

    // undo the thing that happens in split view when return to full-screen
    textlabel.hidden = true

}
}


override func viewDidAppear(animated: Bool) {

widthtimer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "checkwidth", userInfo: nil, repeats: true) 
// runs every hundredth of a second to call the checkwidth function, to check the width of the window.

}

override func viewDidDisappear(animated: Bool) {
widthtimer.invalidate()
}

}

J'espère que cela peut aider tous ceux qui viennent furtivement!

0
owlswipe