¿Cómo puedo usar Autolayout para establecer restricciones en mi UIScrollview?

176

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 contentviewla translatesAutoresizingMaskIntoConstraintsconfiguració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 contentviewy 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:

ingrese la descripción de la imagen aquí

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:

ingrese la descripción de la imagen aquí

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.

usuario1459524
fuente
¿Dónde calcula / establece el tamaño del contenido para su vista de desplazamiento? Refiriéndose a su primer intento usando contentView y dijo que se desplaza demasiado.
Tim
2
Hasta donde yo sé, no se puede configurar el uso contentSizede un UIScrollViewdiseño automático. Y es lo contentSizeque 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.
Guillaume
@Jeff, el tamaño del contenido es fijo, nunca cambia. Establezco el tamaño del contenido en el guión gráfico ingresando la altura y el ancho correctos para la vista de contenido manualmente, y fijo la altura y el ancho con restricciones en el guión gráfico.
user1459524
Imprima su contentSize en tiempo de ejecución, vea si coincide con los valores que ha ingresado. ContentSize determina cuánto desplazamiento se produce, por lo que el problema con su primer intento es hacer con contentSize.
Tim
@Guillaume, entonces, ¿el enfoque de "auto-distribución pura" no es tan puro después de todo? Pero ¿CÓMO configuro el contentSize manualmente? Como mencioné anteriormente, estoy configurando el alto / ancho de la vista de contenido en valores fijos (en el guión gráfico). Pero se desplaza demasiado lejos (2x).
user1459524

Respuestas:

68

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.

Jamie Forrest
fuente
2
¡Gracias por el proyecto de muestra! Funciona, y mientras lo miraba, ¡al principio no pude encontrar ninguna diferencia en mi proyecto! Copié las vistas en mi proyecto, sospechando que no existían restricciones, pero siguió funcionando. Esto me llevó a notar que la restricción final para el último botón de mi proyecto tiene un negativo, ¡frente a él, mientras que el suyo tiene un valor positivo! ¡Cambiar el - a positivo habilitó el desplazamiento! Cuando abro la barra de herramientas Pin, hay dos opciones: Usar el valor de Canvas actual, que es negativo, y la Vista de desplazamiento (usar el valor actual) que es positivo ...?!
user1459524
Ah, sí. El valor negativo en realidad reduciría el tamaño del contenido de la vista de desplazamiento, para que coincida con el hecho de que el borde final debe terminar antes de que finalice el botón. Me alegra que el proyecto de muestra haya ayudado.
Jamie Forrest
Hizo mucho Mira mi respuesta actualizada. El valor final en realidad debería ser 0 (cero) parece.
user1459524
66
Es triste que tengamos que compartir capturas de pantalla en lugar de código. Eso es solo porque Apple alienta a los desarrolladores a usar el generador en lugar de proporcionar una mejor API.
Vladimír Slavík
44
Totalmente poco intuitivo. Los desarrolladores tienen que desperdiciar horas y horas para imaginar qué estaba pasando en la mente de los creadores de XCode.
Josh
49

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):

  • Anchos iguales
  • Alturas iguales
  • Centro Y Alineación
  • Centro X Alineación

Mi estructura:

  UIView
   - ScrollView
    - Subview
    - Subview
    - Subview
    - Subview
    - ...

Este es el resultado final:

Manifestación

Esta es la configuración:

Preparar Pantalla completa

Y aquí está el proyecto .

Espero que esto salve a alguien de IR A DORMIR A LAS 5 AM. :RE

barra invertida-f
fuente
¡Muchas gracias por la ayuda! ¿Cómo obtuviste la subvista del tipo "subview"? Estoy mirando su proyecto en Xcode 6.2, y llama a esos pequeños rectanges "Subview" con la única restricción de que tiene 63px de alto.
Andrew K
1
¡Saludos! Esa "Subvista" es en realidad una UIVIew. Es solo un nombre ... Puedes escribir cualquier cosa allí. Echa un vistazo a esta imagen: cl.ly/image/291f1K2N0V3p En el tema de restricción, las subvistas tienen más que solo una restricción de altura. Consulte la lista completa de restricciones para esas vistas aquí: cl.ly/image/3l061i123j2i
barra invertida-f
1
Todavía no puedo hacer que funcione el desplazamiento: noté que las vistas de las subvistas están "atenuadas" en su proyecto. Después de investigar un poco, parece que esto se debe a que está utilizando 'clases de tamaño'. ¿Cómo afecta esto al desplazamiento? ¿Hay alguna manera de hacer que el desplazamiento funcione sin usar esto?
Andrew K
Además, ¿cómo hizo que su supervista fuera mucho más larga que la longitud predeterminada? Estoy tratando de agregar botones que aparecerán "debajo del pliegue" (o fuera de la pantalla) pero obviamente no puedo agregarlos a la supervista si no puedo arrastrarlos y soltarlos en la supervista ya que no es lo suficientemente grande.
Andrew K
1
después de un largo día de buscar e intentar hacer este diseño de estupidez, encontré esta respuesta y funciona en el primer intento ... Gracias hombre ... me salvas el día ... Me gustaría poder dar mil votos a favor por esta respuesta ...: )
Bobby Stenly
32

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.

ingrese la descripción de la imagen aquí

La pregunta original se refiere a los botones de desplazamiento. Aquí solo uso UIViews 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

  • El UIScrollViewsolo debe usar una subvista. Esta es una 'UIView' que sirve como vista de contenido para contener todo lo que desea desplazarse.
  • Haga que la vista de contenido y la vista de desplazamiento principal tengan alturas iguales para el desplazamiento horizontal. (Anchos iguales para desplazamiento vertical)
  • Asegúrese de que todo el contenido desplazable tenga un ancho establecido y esté anclado en todos los lados.

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,000y la altura 300. Esto solo nos da espacio en el guión gráfico para agregar contenido que se desplazará.

ingrese la descripción de la imagen aquí

Agregar una vista de desplazamiento

Agregue UIScrollVieway fije los cuatro lados a la vista raíz del controlador de vista.

ingrese la descripción de la imagen aquí

Agregar una vista de contenido

Agregue un UIViewcomo una subvista a la vista de desplazamiento. Esta es la clave. No intente agregar muchas subvistas a la vista de desplazamiento. Solo agrega uno UIView. 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.

ingrese la descripción de la imagen aquí

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.

ingrese la descripción de la imagen aquí

Nota:

  • Si hiciéramos que el contenido se desplazara verticalmente, estableceríamos el ancho de la vista de contenido para que sea igual al ancho de la vista de desplazamiento principal.

Agregar contenido

Agrega tres UIViewsy dales todas las restricciones. Usé márgenes de 8 puntos para todo.

ingrese la descripción de la imagen aquí

Restricciones:

  • Vista verde: fija los bordes superior, izquierdo e inferior. Haz el ancho 400.
  • Vista roja: fija los bordes superior, izquierdo e inferior. Haz el ancho 300.
  • Vista púrpura: fija los cuatro bordes de los bordes. Haga el ancho sea cual sea el espacio restante (268 en este caso).

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

Suragch
fuente
9

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):

    UIView *containerView               = [[UIView alloc] init];
    UIScrollView *scrollView            = [[UIScrollView alloc] init];
    [containerView addSubview:scrollView];
    containerView.translatesAutoresizingMaskIntoConstraints = NO;
    scrollView.translatesAutoresizingMaskIntoConstraints    = NO;
    NSDictionary *viewsDictionary       = NSDictionaryOfVariableBindings(containerView, scrollView);

    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|"
                                                                          options:kNilOptions
                                                                          metrics:nil
                                                                            views:viewsDictionary]];
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|"
                                                                          options:kNilOptions
                                                                          metrics:nil

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:

    UIButton *buttonA                   = [[UIButton alloc] init];
    UIButton *buttonB                   = [[UIButton alloc] init];
    UIButton *buttonC                   = [[UIButton alloc] init];
    [scrollView addSubview:buttonA];
    [scrollView addSubview:buttonB];
    [scrollView addSubview:buttonC];
    buttonA.translatesAutoresizingMaskIntoConstraints       = NO;
    buttonB.translatesAutoresizingMaskIntoConstraints       = NO;
    buttonC.translatesAutoresizingMaskIntoConstraints       = NO;

    viewsDictionary                     = NSDictionaryOfVariableBindings(scrollView, buttonA, buttonB, buttonC);

    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[buttonA]-|"
                                                                       options:kNilOptions
                                                                       metrics:nil
                                                                         views:viewsDictionary]];
    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[buttonA]-[buttonB]-[buttonC]-|"
                                                                       options:NSLayoutFormatAlignAllBaseline
                                                                       metrics:nil
                                                                         views:viewsDictionary]];
Infinity James
fuente
Entonces, ¿configuré las restricciones entre scrollView y los botones, y no el containerView y los botones? Creo que esa es la única diferencia que tengo entre tu código y lo que estoy haciendo a través del guión gráfico en este momento.
user1459524
Solo me di cuenta después de la segunda lectura que estás configurando una vista de CONTENEDOR y no una vista de CONTENIDO. Según su código, he recreado todo exactamente en el guión gráfico, y no se desplaza. Editaré mi pregunta con algunas capturas de pantalla.
user1459524
1
Entonces resulta que mi intento de recrear el código en el guión gráfico no era 100% correcto. El valor final para el último botón debe ser exactamente cero, reflejando H: | - [botónA] - [botónB] - [botónC] - | lo cual no es muy obvio cuando trabajas en storyboard (o al menos no lo era para mí) pero ahora después de que el hecho parece trivial. Me encanta el diseño automático, pero esas pequeñas cosas se ponen ya ...
user1459524
Lo que @ user1459524 mencionó fue un problema para mí. Mi vista inferior era un botón y la restricción inferior era -32 por IB. Lo configuré en 0 y se actualizó en IB para ser Bottom Space: superview. Funcionará, también parece que mientras estés en el lado positivo, funcionará. Parece que eso puede ser un error con IB. Espero que ayude a alguien más. También eliminé todas las vistas y las volví a cablear, lo que ayuda cuando trato de diseñarlas, y generalmente no toma mucho tiempo.
Michael
8

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 clase UIScrollView desplaza su contenido cambiando el origen de sus límites. Para que esto funcione con Diseño automático, los bordes superior, izquierdo, inferior y derecho dentro de una vista de desplazamiento ahora significan los bordes de su vista de contenido.

La siguiente figura representa eso: ingrese la descripción de la imagen aquí

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:

  1. Imágenes de las posiciones de las vistas en la vista de contenido.
  2. Agregue espacio superior, derecho, inferior e izquierdo a los bordes de la vista de contenido, además del ancho y alto de estas vistas.

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

Danyun Liu
fuente
5

La siguiente solución funcionó para mí para scrollView con autolayout y sin contentSize :

  1. Arrastre y suelte un scrollView para viewController y aplique las restricciones para cubrir el espacio que desee.
  2. Arrastre y suelte una UIView dentro de scrollView y haga que cubra todo el espacio de scrollView y aplique restricciones para ser el espacio superior, izquierdo, derecho e inferior de scrollView.
  3. Establezca la altura (y el ancho si se requiere desplazamiento horizontal) de la vista interior según la necesidad de desplazamiento. Esta parte también se puede hacer desde el código si es necesario.
  4. Crítico . Después de establecer la altura en algún valor grande en el punto (3), regrese al punto (2) y asegúrese de establecer los valores superior, izquierdo, derecho e inferior nuevamente en cero, ya que Xcode puede haberlos cambiado para usted cuando fuerza cambió la altura en (3).

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.

zeeawan
fuente
Esta es realmente la mejor respuesta aquí. ¡Gracias!
Fattie
4

Supongo que tiene problemas con el contentSize. Echa un vistazo a esta publicación de blog sobre cómo manejar el contentSizeuso 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 funciona

Edward Huynh
fuente
3

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.

Travis
fuente
3

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.

Robert Atkins
fuente
3

Debe organizar su diseño como este
ViewControllerViewcontiene ScrollView, ScrollViewcontiene ContainerView, ContainerViewcontiene 2Labels
ingrese la descripción de la imagen aquí

Luego siga 3 pasos para hacer que su ScrollViewlata se desplace

  1. Poner el ScrollViewpin (arriba / derecha / abajo / izquierda) enViewControllerView
    • Poner el ContainerViewpin (arriba / derecha / abajo / izquierda) enScrollView
    • Establecer Horizontally in Container( no establecer Vertically in Container)
    • Label1pin ( arriba / derecha / izquierda) aContainerView
    • Label1pin (derecha / izquierda / abajo ) hacia arribaContainerView y hacia arribaLabel1

ingrese la descripción de la imagen aquí

AQUÍ está el proyecto de demostración

Espero que esto ayude

Phan Van Linh
fuente
1

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:

  • Comience con algo pequeño: incluso si eso significa recrear las vistas de su guión gráfico, comience con solo unos pocos elementos y construya sus vistas lentamente, asegurándose de probar que el desplazamiento funciona después de agregar algunos elementos.
  • Desactivar traduceAutoresizingMaskIntoConstraints en todo: esta siempre fue la causa de los conflictos de restricción para mí.
  • Establezca sus restricciones UIScrollView correctamente: asegúrese de que la vista de desplazamiento esté conectada en todos los lados a la vista principal, de lo contrario, simplemente no se expandirá en absoluto.
Mella
fuente
1

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.

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewWidthConstraint; 
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewHeightConstraint;

Luego en viewDidLoad

CGSize viewSize = self.view.frame.size;
self.contentViewWidthConstraint.constant = viewSize.width;
self.contentViewHeightConstraint.constant = viewSize.height;

Funciona genial.

Cristian Pena
fuente
1

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:

  1. Crea la vista de desplazamiento y llénalo con los objetos que quieras
  2. Activar diseño automático
  3. Luego, centre la vista de desplazamiento vertical y horizontalmente Vista de desplazamiento central
  4. Seleccione la Vista y luego 'Agregar restricciones faltantes' ; esto hace lo suyo
  5. El resultado es que se generan muchas restricciones. Hay 2 nuevas creadas para la vista: 'Horiz space scrollview to View' y 'Vert space scrollview to view' o viceversa.
  6. Elimine la 'vista de desplazamiento del espacio Horiz para ver' para que ahora tenga 3 restricciones en la vista. El 2 para ingresar a la vista de desplazamiento en la vista y el que establece un espacio vertical entre la vista de desplazamiento y la vista
  7. Ahora vincule la restricción Vert a su código haciendo clic y Ctrl arrastrándolo al archivo de encabezado y creando un IBOutlet NSLayoutConstraint (llamé al mío restrictintVertVtoSV)
  8. 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)

    if (IPAD)

    {self.constraintVertVtoSV.constant = 150.0; }

  9. ahora debería ejecutarse en todos los dispositivos y estar correctamente centrado y seguir desplazándose correctamente.

Chico
fuente
1

Si, como yo, solo usa contenido estático sin restricciones dentro de la subvista, como puede hacer así:

override func viewDidLayoutSubviews() {
    scrollView.contentSize = CGSizeMake(320, 800)
}
Antzi
fuente
1

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.

// Either one of these additional constraints are required to get autolayout to correctly layout the contentView. Otherwise contentView size is its minimum required size
scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: .CenterX, relatedBy: .Equal, toItem: scrollView, attribute: .CenterX, multiplier: 1.0, constant: 0))
scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: scrollView, attribute: .Width, multiplier: 1.0, constant: 0.0))

Anclar los bordes de la vista de contenido a la vista de desplazamiento utilizando restricciones visuales del formulario,

let cvConstraints = ["H:|[contentView]|", "V:|[contentView]|"]

Utilizo una rutina para recorrer el conjunto y agregarlos a scrollView.

David
fuente
1

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.

i89
fuente
1

En Swift puedes usar esta solución de trabajo.

Contracciones

ScrollView: Inicio, Trailing, Arriba, Abajo = Superview

ContentView: 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.

extension UIView {

    func setupContentViewForViewWithScroll(contentView vwContent : UIView) {
        //Set constraint for scrollview content
        let constraint = NSLayoutConstraint(item: vwContent, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: self.bounds.size.width)
        vwContent.addConstraint(constraint)
        self.layoutSubviews()
    }

}

Y en el controlador de vista viewDidLayoutSubviewssimplemente llamo a este método:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.view.setupContentViewForViewWithScroll(contentView: vwContent)
}
Ibrahim Yildirim
fuente
0

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.

Rinaldo
fuente