Básicamente, quiero que mis subvistas se coloquen de manera diferente según la orientación del iPad (vertical u horizontal) utilizando las clases de tamaño introducidas en xcode 6. He encontrado numerosos tutoriales que explican cómo las diferentes clases de tamaño están disponibles para Iphones en vertical y horizontal en el IB. Sin embargo, parece que no hay ninguno que cubra los modos de paisaje o retrato individual para el iPad en IB. ¿Alguien puede ayudar?
objective-c
ios8
size-classes
adaptive-ui
neelIVP
fuente
fuente
Respuestas:
Parece que la intención de Apple es tratar ambas orientaciones del iPad de la misma manera, pero como algunos de nosotros estamos descubriendo, existen razones de diseño muy legítimas para querer variar el diseño de la interfaz de usuario para iPad vertical frente a iPad horizontal.
Desafortunadamente, el sistema operativo actual no parece brindar soporte para esta distinción ... lo que significa que volvemos a manipular las restricciones de diseño automático en el código o soluciones alternativas similares para lograr lo que idealmente deberíamos poder obtener de forma gratuita utilizando la interfaz de usuario adaptable .
No es una solución elegante.
¿No hay una manera de aprovechar la magia que Apple ya ha incorporado en IB y UIKit para usar una clase de tamaño de nuestra elección para una orientación determinada?
~
Al pensar en el problema de manera más genérica, me di cuenta de que las 'clases de tamaño' son simplemente formas de abordar varios diseños que se almacenan en IB, de modo que se puedan llamar según sea necesario en tiempo de ejecución.
De hecho, una 'clase de tamaño' es en realidad solo un par de valores de enumeración. Desde UIInterface.h:
Entonces, independientemente de cómo Apple haya decidido nombrar estas diferentes variaciones, fundamentalmente, son solo un par de números enteros que se usan como una especie de identificador único, para distinguir un diseño de otro, almacenado en IB.
Ahora, suponiendo que creamos un diseño alternativo (usando una clase de tamaño no utilizada) en IB, digamos, para iPad Portrait ... ¿hay alguna manera de que el dispositivo use nuestra elección de clase de tamaño (diseño de interfaz de usuario) según sea necesario en tiempo de ejecución? ?
Después de probar varios enfoques diferentes (menos elegantes) del problema, sospeché que podría haber una forma de anular la clase de tamaño predeterminada mediante programación. Y hay (en UIViewController.h):
Por lo tanto, si puede empaquetar la jerarquía de su controlador de vista como un controlador de vista 'secundario' y agregarlo a un controlador de vista principal de nivel superior ... entonces puede anular condicionalmente al niño para que piense que es una clase de tamaño diferente al predeterminado desde el sistema operativo.
Aquí hay una implementación de muestra que hace esto, en el controlador de vista 'padre':
Como demostración rápida para ver si funcionaba, agregué etiquetas personalizadas específicamente a las versiones 'Regular / Regular' y 'Compacta / Regular' del diseño del controlador secundario en IB:
Y así es como se ve funcionando, cuando el iPad está en ambas orientaciones:
¡Voila! Configuraciones de clases de tamaño personalizado en tiempo de ejecución.
Con suerte, Apple hará que esto sea innecesario en la próxima versión del sistema operativo. Mientras tanto, este puede ser un enfoque más elegante y escalable que jugar programáticamente con restricciones de diseño automático o hacer otras manipulaciones en el código.
~
EDITAR (4/6/15): tenga en cuenta que el código de muestra anterior es esencialmente una prueba de concepto para demostrar la técnica. Siéntase libre de adaptarse según sea necesario para su propia aplicación específica.
~
EDITAR (24/7/15): Es gratificante que la explicación anterior parezca ayudar a desmitificar el problema. Aunque no lo he probado, el código de mohamede1945 [abajo] parece una optimización útil para propósitos prácticos. No dude en probarlo y hacernos saber lo que piensa. (En aras de la integridad, dejaré el código de muestra anterior como está).
fuente
UITraitCollection
está lo suficientemente optimizado yoverrideTraitCollectionForChildViewController
rara vez se llama por lo que no debería ser un problema hacer la verificación de ancho y crearlo luego.Como resumen de la larga respuesta de RonDiamond. Todo lo que necesita hacer es en su controlador de vista raíz.
C objetivo
Rápido:
Luego, en storyborad, use ancho compacto para vertical y ancho regular para horizontal.
fuente
- (UITraitCollection *)traitCollection
lugar deoverrideTraitCollectionForChildViewController
. Además, las restricciones deben coincidir con las colecciones de rasgos, por lo que wC (hAny).El iPad tiene el rasgo de tamaño "normal" tanto para las dimensiones horizontales como verticales, sin distinción entre retrato y paisaje.
Estos rasgos de tamaño se pueden anular en su
UIViewController
código de subclase personalizado , mediante un métodotraitCollection
, por ejemplo:Esto le da al iPad los mismos rasgos de tamaño que el iPhone 7 Plus. Tenga en cuenta que otros modelos de iPhone generalmente tienen el rasgo de 'ancho compacto' (en lugar de ancho regular) independientemente de la orientación.
La imitación del iPhone 7 Plus de esta manera permite que ese modelo se use como un sustituto del iPad en el Interface Builder de Xcode, que desconoce las personalizaciones en el código.
Tenga en cuenta que la Vista dividida en el iPad puede usar características de tamaño diferentes a las del funcionamiento normal de pantalla completa.
Esta respuesta se basa en el enfoque adoptado en esta publicación de blog , con algunas mejoras.
Actualización 2019-01-02: actualizado para corregir la barra de estado oculta intermitente en el panorama del iPad y el posible pisoteo de rasgos (más nuevos) en
UITraitCollection
. También señaló que la documentación de Apple en realidad recomienda no anulartraitCollection
, por lo que en el futuro pueden surgir problemas con esta técnica.fuente
traitCollection
propiedad sea de solo lectura: developer.apple.com/documentation/uikit/uitraitenvironment/…La respuesta larga y útil de RonDiamond es un buen comienzo para comprender los principios, sin embargo, el código que funcionó para mí (iOS 8+) se basa en un método primordial
(UITraitCollection *)traitCollection
Por lo tanto, agregue restricciones en InterfaceBuilder con variaciones para Ancho - Compacto, por ejemplo, para la propiedad de restricción Instalada. Entonces Ancho: Cualquiera será válido para paisaje, Ancho: Compacto para Retrato.
Para cambiar las restricciones en el código según el tamaño del controlador de vista actual, simplemente agregue lo siguiente en su clase UIViewController:
fuente
¿Qué tan diferente será su modo de paisaje que su modo de retrato? Si es muy diferente, podría ser una buena idea crear otro controlador de vista y cargarlo cuando el dispositivo esté en horizontal
Por ejemplo
fuente
Versión Swift 5. Funciona bien.
fuente
Código Swift 3.0 para la solución @RonDiamond
fuente