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.
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);
}
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-CNotez que, dans Swift, l’objet window
est un double facultatif ... WTF !
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
}
}
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é.
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())
}
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.
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!
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)
}
}
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;
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
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);
}
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!