He pasado dos días probando las diversas soluciones para los enfoques de Autolayout mixto y puro para lograr lo que era una configuración trivial de vista de desplazamiento antes del autolayout, y ahora es oficial: debo ser demasiado estúpido. Estoy configurando esto principalmente en Storyboard (bueno, así es como es).
Así que aquí está mi petición de ayuda.
Viewtree:
UIView
-UIView
-UIView
..-UIScrollview
...-UIButton
...-UIButton
...-UIButton
Se supone que los botones se desplazan horizontalmente (de izquierda a derecha y viceversa). ¿Alguien puede decirme cómo establecer las restricciones para lograr esto usando Autolayout puro?
-
He intentado el enfoque mixto, así:
UIView
- UIView
- UIView
..-UIScrollview
...-UIView (contentview)
....-UIButton
....-UIButton
....-UIButton
... y establecer restricciones de ancho y alto fijas para contentview
la translatesAutoresizingMaskIntoConstraints
configuración y según la nota técnica de Apple. Los botones y la vista de desplazamiento se configuran mediante restricciones. Esto hace que el scrollview se desplace (sí) pero, por desgracia, ¡se desplaza demasiado! Por lo que puedo decir, el ancho de desplazamiento se duplica de alguna manera de lo que configuré la vista de contenido en ??? !!! ???
También probé el enfoque de autolayout puro, con contentview
y sin. Todas las vistas son translatesAutoresizingMaskIntoConstraints=NO
, excepto self.view
. Los botones tienen restricciones de ancho / alto fijas y están anclados a los cuatro bordes de la vista de desplazamiento. Nada se desplaza.
Así que estoy totalmente desconcertado por qué no puedo hacer que funcione correctamente. Cualquier ayuda es muy apreciada, y si necesita cualquier otra información, ¡pregunte!
Captura de pantalla ACTUALIZADA con solución - restricciones buttonZ:
EDITAR @ Jamie Forrest Entonces, la solución resulta ser la restricción de seguimiento incorrecta en el último botón. En lugar de 6441, el valor que había establecido era negativo, -6441. Lo complicado es que, al establecer el valor en el guión gráfico, hay dos opciones en la barra de herramientas Pin:
El valor actual del lienzo es negativo (lo que lleva a que no haya desplazamiento), y la opción a continuación es positiva (activación del desplazamiento). Esto significa que no soy estúpido, pero al menos medio ciego, supongo. Aunque, en mi defensa, ¿no es algo inquietante que XCode no muestre un error para la configuración "incorrecta"?
EDITADO DE NUEVO Ahora esto es divertido ... cambiando el valor final de -6441 (sin desplazamiento) a 6441 desplazamiento habilitado. ¡Pero mi viejo amigo, el "demasiado contenido" estaba de regreso, lo que condujo a un tamaño de contenido dos veces más grande de lo que debería ser! ¡La solución para obtener el desplazamiento de contenido correcto fue establecer la restricción final a CERO! Esto no es obvio cuando se trabaja en Storyboard, pero al mirar el código de @Infinity James, es lo que debería ser.
fuente
contentSize
de unUIScrollView
diseño automático. Y es locontentSize
que define cuánto puede desplazarse. Por lo tanto, tendrá que configurar esto manualmente en algún lugar eventualmente. Por lo demás, puede usar restricciones de diseño para configurar marcos de vista uno con respecto al otro.Respuestas:
Es difícil ver los valores exactos y la configuración de sus restricciones ya que las ha pegado aquí, por lo que no estoy seguro de mirar en sus capturas de pantalla dónde se equivocó.
En lugar de una explicación de lo que está mal en su configuración, he creado un proyecto de muestra básico con una jerarquía de vistas y una configuración de restricciones muy similares a las que usted describe. El desplazamiento horizontal funciona como se esperaba en el proyecto de muestra, que utiliza el enfoque "Pure AutoLayout" que Apple describe en la Nota técnica .
También tuve muchos problemas originalmente para hacer que Auto Layout funcionara
UIScrollView
. La clave para que funcione es asegurarse de que todos los elementos en la vista de desplazamiento, tomados en conjunto, tengan restricciones que eventualmente se vinculen a todos los lados de la vista de desplazamiento y que contribuyan a que el sistema AutoLayout pueda determinar un tamaño de contenido para vista de desplazamiento que será más grande que su marco. Parece que estaba tratando de hacer eso en su código, pero tal vez tenía algunas restricciones superfluas que estaban haciendo que contentSize fuera demasiado pequeño.También es de destacar, como otros mencionaron, con AutoLayout y UIScrollview, ya no establece explícitamente contentSize. El sistema AutoLayout calcula el tamaño del contenido en función de sus restricciones.
También encontré que este capítulo del libro electrónico es muy útil para hacerme entender cómo funciona todo esto. Espero que todo esto ayude.
fuente
LOL bienvenido al club de estupidez. Soy uno de los fundadores. :RE
Para el desplazamiento VERTICAL : la única forma en que podía hacer que funcionara (iOS 8, Xcode 6 y distribución automática pura) era agregar las siguientes restricciones a mi Vista de desplazamiento (todo relacionado con la supervista):
Mi estructura:
Este es el resultado final:
Esta es la configuración:
Pantalla completa
Espero que esto salve a alguien de IR A DORMIR A LAS 5 AM. :RE
fuente
Ejemplo autocontenido simple
A juzgar por el alto número de votos sobre la pregunta y el bajo número de votos sobre las respuestas, las personas no encuentran una solución rápida y comprensible aquí. Déjame intentar agregar uno. Este proyecto es un ejemplo autónomo realizado completamente en Interface Builder. Debería poder resolverlo en 10 minutos o menos. Luego puede aplicar los conceptos que aprendió a su propio proyecto.
La pregunta original se refiere a los botones de desplazamiento. Aquí solo uso
UIView
s pero pueden representar cualquier vista que desee. También elegí el desplazamiento horizontal porque las capturas de pantalla del guión gráfico son más compactas para este formato. Sin embargo, los principios son los mismos para el desplazamiento vertical.Conceptos clave
UIScrollView
solo debe usar una subvista. Esta es una 'UIView' que sirve como vista de contenido para contener todo lo que desea desplazarse.Comience un nuevo proyecto
Puede ser solo una aplicación de vista única.
Storyboard
En este ejemplo haremos una vista de desplazamiento horizontal. Seleccione el Controlador de vista y luego elija Forma libre en el Inspector de tamaño. Haz el ancho
1,000
y la altura300
. Esto solo nos da espacio en el guión gráfico para agregar contenido que se desplazará.Agregar una vista de desplazamiento
Agregue
UIScrollView
ay fije los cuatro lados a la vista raíz del controlador de vista.Agregar una vista de contenido
Agregue un
UIView
como una subvista a la vista de desplazamiento. Esta es la clave. No intente agregar muchas subvistas a la vista de desplazamiento. Solo agrega unoUIView
. Esta será su vista de contenido para las otras vistas que desea desplazar. Ancle la vista de contenido a la vista de desplazamiento en los cuatro lados.Alturas iguales
Ahora en el Esquema del documento, Commandhaga clic en la vista de contenido y en la vista principal de la vista de desplazamiento para seleccionarlos a ambos. Luego configure las alturas para que sean iguales ( Controlarrastre desde la Vista de contenido a la Vista de desplazamiento). Esto también es clave. Debido a que nos estamos desplazando horizontalmente, la vista de contenido de la vista de desplazamiento no sabrá cuán alta debería ser a menos que la configuremos de esta manera.
Nota:
Agregar contenido
Agrega tres
UIView
sy dales todas las restricciones. Usé márgenes de 8 puntos para todo.Restricciones:
Establecer las restricciones de ancho también es clave para que la vista de desplazamiento sepa qué tan amplia será su vista de contenido.
Terminado
Eso es todo. Puedes ejecutar tu proyecto ahora. Debería comportarse como la imagen de desplazamiento en la parte superior de esta respuesta.
Para el desplazamiento vertical, simplemente intercambie todas las direcciones de ancho y alto en este ejemplo (probado y funcionando).
Estudio adicional
fuente
ContentSize se establece implícitamente aplicando las restricciones dentro de UIScrollView.
Por ejemplo, si tiene un UIScrollView dentro de una UIView se verá así (como estoy seguro de que sabe):
Eso configurará scrollView para llenar el tamaño de containerView (por lo que containerView tendrá que ser de cierto tamaño).
Luego puede ajustar el tamaño de contenido de UIScrollView configurándolo implícitamente para que sea lo suficientemente grande como para mantener los botones como este:
fuente
Hay tantas preguntas sobre el uso de AutoLayout con UIScrollView, el punto clave que ignoramos es que las vistas internas de UIScrollView imponen restricciones a la vista de contenido, pero no a UIScrollView. Consulte la Nota técnica TN2154 , puede encontrar:
La siguiente figura representa eso:
Puede encontrar que el espacio final es de 500 puntos, si la restricción se establece en UIScrollView, la vista se colocará incorrectamente y se debe actualizar su marco. Sin embargo, no hay advertencias ni errores. Porque todas las restricciones están en contra de la vista de contenido.
UIScrollView calculará el tamaño de la vista de contenido de acuerdo con las restricciones de las vistas internas. (Por ejemplo, el tamaño del contenido: ancho = 100 (espacio inicial) + 200 (ancho de la vista) + 500 (espacio final), altura = 131 (espacio superior) + 200 (altura) + 269 (espacio inferior)
Cómo agregar restricciones para las vistas en UIScrollView:
Y todo está hecho.
Una manera fácil de lidiar con AutoLayout con vista de desplazamiento es agregar una vista de contenedor que contenga todas las subvistas en la vista de desplazamiento.
Conclusión: el punto clave para comprender AutoLayout con UIScrollView es que las vistas internas imponen restricciones a la vista de contenido, pero no a UIScrollView en sí.
código de ejemplo adjunto
fuente
La siguiente solución funcionó para mí para scrollView con autolayout y sin contentSize :
Y tu estas listo. Ahora, puede agregar cualquier número de controles en esta vista y aplicar las restricciones relevantes entre sí (que no parecen funcionar sin esta vista). Si no desea utilizar esta vista, deberá aplicar restricciones para cada control relacionado con scrollView (no relacionados entre sí).
El consejo abrumador ..............
Crítico . Digamos por claridad que UIScrollView tiene 1000 de ancho y 100 de alto. (De hecho, normalmente estos valores serían dinámicos, por supuesto, dependiendo del ancho del dispositivo, etc. Pero por ahora solo digamos 1000 de ancho y 100 de alto). Digamos que está haciendo un desplazamiento horizontal. Así que coloque una UIView dentro de UIScrollView. (Esa es la "vista de contenido".) Establezca las cuatro restricciones de la vista de contenido superior, inferior, inicial, posterior a la vista de desplazamiento. Haga que todos sean cero, incluso si eso parece incorrecto. Establece la altura del contenido UIView en 100 y olvídate de eso. Ahora: desea desplazarse horizontalmente, así que configure el ancho de la vista de contenido para que sea, digamos, 1225.
Tenga en cuenta que el ancho de la vista de contenido ahora es 225 mayor que el ancho de la vista de desplazamiento principal. Eso está bien: de hecho, DEBES hacer eso. Tenga en cuenta que
... NO establezca el ancho final a negativo 225 ...
pensaría que tiene que "igualar" los anchos como lo haría normalmente . Pero si haces eso, no funcionará en absoluto.
Debe establecer los números iniciales y finales en CERO , nunca negativos (aunque el ancho sea "mayor")
Curiosamente, en realidad puede establecer los números iniciales / finales a cualquier valor positivo (intente decir "50") y le da una especie de margen de rebote. (A menudo se ve muy bien: pruébelo). Cualquier valor negativo en cualquier extremo se "romperá en silencio".
Tenga en cuenta que, exasperantemente, a menudo Xcode (a partir de 7.3.1 de todos modos),
¡'útilmente' establecerá esos valores para usted en números negativos!
porque trata de contarlos automáticamente por ti. Si es así, se romperá en silencio. Establezca los cuatro valores a cero en primera instancia. Y establezca el ancho de la vista de contenido mucho más ancho que el "1000" en el ejemplo.
Editado: Terminé usando UITableView en lugar de UIScrollView para la mayoría de mis requisitos. Como tableView me parece mucho más flexible y dinámico.
fuente
Supongo que tiene problemas con el
contentSize
. Echa un vistazo a esta publicación de blog sobre cómo manejar elcontentSize
uso de un enfoque de diseño automático "puro". La esencia de esto es que sus restricciones definen implícitamente el tamaño del contenido. NUNCA lo configura explícitamente cuando usa AutoLayout. He adjuntado un proyecto de ejemplo al final de la publicación del blog para demostrar cómo funcionafuente
Hay una pieza en las notas técnicas que puede haber revisado. Puede establecer implícitamente el tamaño del contenido de una vista de desplazamiento utilizando restricciones fijadas en los bordes de la vista de desplazamiento.
Aquí hay un ejemplo simple. Cree un guión gráfico con una vista, que tenga una vista de desplazamiento. Establezca las restricciones de las vistas de desplazamiento para que se ajuste al tamaño de la vista en la que lo colocó.
Dentro de esa vista de desplazamiento, agregue una vista única. Establezca explícitamente el tamaño de esa vista utilizando restricciones (y asegúrese de que el tamaño sea mayor que la vista de desplazamiento).
Ahora agregue cuatro restricciones más a esa vista interna que bloquea los cuatro bordes de la vista interna a su vista de desplazamiento principal. Esas cuatro restricciones harán que el tamaño del contenido se expanda para acomodar la vista interna.
Si tiene varias vistas que desea agregar a una vista de desplazamiento, por ejemplo, dispuestas horizontalmente, bloquearía el lado izquierdo de la primera subvista a la izquierda de la vista de desplazamiento, bloquearía las subvistas entre sí horizontalmente y la derecha lado de la última vista secundaria al lado derecho de la vista de desplazamiento. Esas restricciones obligarían a expandir el tamaño del contenido de la vista de desplazamiento para acomodar todas las subvistas y sus restricciones.
fuente
Si su pregunta es "¿Cómo pongo un montón de UITextFields en un UIScrollView de desplazamiento vertical para que se aparten del teclado cuando tienen el foco", la mejor respuesta es:
No lo hagas
Utilice un UITableViewController con celdas estáticas en su lugar.
Obtiene este comportamiento de desplazamiento libre de forma gratuita, Y todas las inserciones de contenido Solo funcionan si su controlador de vista se muestra dentro de un UINavigationController.
fuente
Debe organizar su diseño como este
ViewControllerView
contieneScrollView
,ScrollView
contieneContainerView
,ContainerView
contiene 2Labels
Luego siga 3 pasos para hacer que su
ScrollView
lata se desplaceScrollView
pin (arriba / derecha / abajo / izquierda) enViewControllerView
ContainerView
pin (arriba / derecha / abajo / izquierda) enScrollView
Horizontally in Container
( no establecerVertically in Container
)Label1
pin ( arriba / derecha / izquierda) aContainerView
Label1
pin (derecha / izquierda / abajo ) hacia arribaContainerView
y hacia arribaLabel1
Espero que esto ayude
fuente
El enfoque de distribución automática pura funciona a la perfección, pero es bastante complicado configurarlo si está migrando desde la no distribución automática. Lo he hecho varias veces y tengo algunos consejos generales:
fuente
Después de algún tiempo lidiando con este problema, finalmente encontré una solución. Estoy trabajando con storyboards de tamaño de clase universal (600x600). Creé una UIView (contentView) del tamaño de scrollView y creé restricciones a Top, Bottom, Leading y Trailing a scrollView. Luego recorté manualmente el tamaño de contentView a 600x600. El guión gráfico dejó de intentar cambiar el tamaño de todo y pude trabajar, pero la vista se veía horrible en el dispositivo o simulador real. Hice 2 salidas de restricción de estos tamaños recortados.
Luego en viewDidLoad
Funciona genial.
fuente
Pasé días tratando de encontrar una solución sobre cómo usar AutoLayout ver una vista de desplazamiento incorporada, para centrar la vista de desplazamiento en la pantalla visible, que funciona en todos los dispositivos / dimensiones de la pantalla, así como con la rotación de la pantalla.
Pasé días tratando de hacerlo solo con Autolayout, y me acerqué pero nunca lo suficientemente cerca. Así que al final también tuve que agregar 3 líneas de código por pantalla, en viewDidLoad.
Ver solución a continuación:
Ahora vaya al archivo .m y agregue estas líneas de código en viewDidLoad (juegue con la cantidad de relleno para obtener el centrado vertical correcto)
{self.constraintVertVtoSV.constant = 150.0; }
ahora debería ejecutarse en todos los dispositivos y estar correctamente centrado y seguir desplazándose correctamente.
fuente
Si, como yo, solo usa contenido estático sin restricciones dentro de la subvista, como puede hacer así:
fuente
Problema similar que tengo hoy con iOS 8.4, Xcode 6.4
Hay una vista que contiene una vista de desplazamiento, que contiene una vista de contenido (UIView) que contiene subvistas.
Todo es diseño automático en todas partes. Los bordes de la vista de desplazamiento se fijan a los bordes de las vistas principales con restricciones. Los bordes de la vista de contenido están anclados a los bordes de la vista de desplazamiento con restricciones.
Originalmente, la vista de contenido se negaría a dimensionar como el ancho completo de la vista de desplazamiento. Tuve que agregar una restricción adicional en la vista de contenido para que su ancho coincida con la vista de desplazamiento principal. O podría establecer una restricción contentView.centerX == scrollView.centerX. Cualquiera de los dos, además de fijar los bordes, de repente hizo que el contenido se visualizara correctamente.
Anclar los bordes de la vista de contenido a la vista de desplazamiento utilizando restricciones visuales del formulario,
Utilizo una rutina para recorrer el conjunto y agregarlos a scrollView.
fuente
Me enfrenté a un problema similar. Establecí todas las restricciones y siempre me preguntaba por qué todavía cambia el tamaño de algunas subvistas. Mi solución fue establecer clipsToBounds en YES.
fuente
En Swift puedes usar esta solución de trabajo.
Contracciones
ScrollView
: Inicio, Trailing, Arriba, Abajo = SuperviewContentView
: Inicio, Trailing, Arriba, Abajo = ScrollView. Altura fija / relativa al contenido.Puede establecer la restricción de ancho (contentView) para igualar la vista general de las vistas de desplazamiento, pero seleccione eliminar eliminar en el tiempo de compilación porque agregará esa restricción mediante programación. Esto es solo para que el IB no se queje con advertencias.
Y en el controlador de vista
viewDidLayoutSubviews
simplemente llamo a este método:fuente
Sé que esta es una solución simple y no es lo que Apple sugiere en el documento, pero funcionó para mí dos veces, con contenido diferente y se puede configurar muy rápidamente: en el controlador de vista del guión gráfico, inserte UIView. En UIView, inserte una vista de tabla, dinámica, 0 celdas prototipo, estilo plano o agrupado. En la Vista de tabla, inserte una Vista de desplazamiento, en la Vista de desplazamiento, inserte contenido. Eso es, no hay configuraciones en el controlador de vista personalizado.
fuente