mini - Detecta si la aplicación se está ejecutando en modo Slide Over o Split View en iOS 9
split view ipad pro (11)
En iOS 9, ¿es posible detectar cuándo se está ejecutando una aplicación en el modo Slide Over o Split View de iOS 9?
Intenté leer la documentation de Apple sobre la multitarea de iOS 9, pero no he tenido suerte con esto ...
Pregunto porque podría tener una función en mi aplicación que me gustaría desactivar cuando la aplicación se abra en una diapositiva.
¡Y llegué muy tarde a la fiesta! Pero, no obstante, aquí hay una solución simple y rápida al problema. Usando let width = UIScreen.mainScreen().applicationFrame.size.width
podemos detectar el ancho de la ventana de mi aplicación, y luego tener cosas que suceden cuando es más pequeño que un cierto número (es decir, en la pantalla del iPhone o en vista dividida), útil hacer que sucedan cosas diferentes en pantallas más pequeñas. Para que la computadora verifique el ancho una y otra vez, podemos ejecutar un NSTimer cada centésima de segundo, y luego hacer cosas si el ancho es más alto / más bajo que algo.
Algunas medidas para ti (tienes que decidir qué ancho hacer que las cosas ocurran arriba / abajo): iPhone 6S Plus: 414.0mm
iPhone 6S: 375.0 mm
iPhone 5S: 320.0 mm
iPad (retrato): 768.0 mm
iPad (vista dividida de 1/3): 320.0 mm
iPad Air 2 (1/2 vista dividida): 507.0 mm
iPad (paisaje): 1024.0 mm
Aquí hay un fragmento de código:
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 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()
}
}
¡Espero que esto pueda ayudar a cualquiera que venga a echar un vistazo!
Añadiendo a la respuesta de @Tamas:
Aquí está el fragmento de código que mantendrá automáticamente esta bandera independientemente de la rotación.
-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
{
// simply create a property of ''BOOL'' type
isRunningInFullScreen = CGRectEqualToRect([UIApplication sharedApplication].delegate.window.frame, [UIApplication sharedApplication].delegate.window.screen.bounds);
}
Al intentar [UIScreen mainScreen] .bounds, self.window.screen.bounds, self.window.frame, UIApplication.sharedApplication.keyWindow.frame y así sucesivamente, la única solución que funcionaba era el método obsoleto.
CGRect frame = [UIScreen mainScreen].applicationFrame;
Que arreglé de esta manera
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;
Después de mucho ''retocar'', he encontrado una solución para mi aplicación que puede funcionar para usted:
En AppDelegate.swift, crea la siguiente variable:
var slideOverActive: Bool = false
Luego, en TODOS los controles de vista, agregue el UIApplicationDelegate a la definición de Clase, cree una variable appDelegate y luego agregue la siguiente función 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
}
}
}
}
}
Luego, en cualquier parte del código que desee verificar si el deslizamiento está activo o no, simplemente verifique:
if appDelegate.slideOverActive == true {
// DO THIS
} else {
// DO THIS
}
Es un poco una solución, pero funciona para mí en este momento.
¡Rastros felices!
Escribí una biblioteca SizeClasser
basada en la biblioteca de @Michael Voccola.
Puede inicializarlo con el traitCollection
de su controlador de vista y detectar vistas divididas, así como orientación específica del dispositivo.
Así que podría escribir su código específicamente 1/3 de vista dividida horizontal o 1/3 de vista de división dividida, lo que UITraitCollection
no le da una manera de detectarlos.
https://github.com/cemolcay/SizeClasser
La clase de tamaño horizontal será compacta cuando esté en deslizamiento sobre o 33% de vista dividida. No creo que puedas detectar una vez que vas al 50% o al 66%.
Llego tarde a la fiesta, pero si quieres una propiedad que funcione independientemente de la orientación, prueba esta:
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
}
}
Puede ver both -willTransitionToTraitCollection: withTransitionCoordinator: para la clase de tamaño y viewWillTransitionToSize: withTransitionCoordinator: para el CGSize de su vista. Sin embargo, no se recomienda la codificación en valores de tamaño.
Recientemente tuve que determinar el estilo de visualización de una aplicación, incluyendo, no solo si cambió a vista dividida o deslizante, sino también qué parte de la pantalla se estaba utilizando para la aplicación (completo, 1/3, 1/2, 2/3). Agregar esto a una subclase ViewController fue capaz de resolver el problema.
/// 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())
}
Simplemente verifica si tu ventana ocupa toda la pantalla:
BOOL isRunningInFullScreen = CGRectEqualToRect([UIApplication sharedApplication].delegate.window.frame, [UIApplication sharedApplication].delegate.window.screen.bounds);
Si esto es falso, se está ejecutando en una vista dividida o una diapositiva.
Aquí está el código cortado que mantendrá automáticamente esta bandera independientemente de la rotación
-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
{
// simply create a property of ''BOOL'' type
isRunningInFullScreen = CGRectEqualToRect([UIApplication sharedApplication].delegate.window.frame, [UIApplication sharedApplication].delegate.window.screen.bounds);
}
Solo otra forma de volver a empaquetar todo esto
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)
}
}
entonces puedes simplemente
-
UIApplication.shared.isSplitOrSlideOver
en Swift -
UIApplication.sharedApplication.isSplitOrSlideOver
en Objective-C
Tenga en cuenta que, en Swift, el objeto window
es un doble opcional ... ¡ WTF !