UIScrollView contentSize no funciona

Puse un UIScrollView en la view mi plumilla y lo IBOutlet una propiedad de IBOutlet .

Ahora, cuando hago esto en mi método viewDidLoad , parece que no tiene ningún efecto en contentSize :

 self.sv.backgroundColor = [UIColor yellowColor]; // this works CGSize size = CGSizeMake(1000.0, 1000.0); [self.sv setContentSize:size]; // this does not 

Se comporta como si contentSize fuera el mismo que el marco. ¿Que esta pasando? Esto comenzó a funcionar cuando apagué AutoLayout. ¿Por qué?

Yo tuve el mismo problema. El diseño automático de UIScrollView está mal.

UIView : coloque todo en UIScrollView en otra UIView y coloque esa UIView como hija única de UIScrollView . Luego puede usar Diseño automático.

Si las cosas cercanas al final están en mal estado (al final de cualquier dirección en la que se UIScrollView su UIScrollView ), cambie la restricción al final para tener la prioridad más baja posible.

Probé viewWillLayoutSubviews para actualizar el contentSize de scrollView, funcionó para mí.

 - (void)viewDidLayoutSubviews { [self.bgScrollView setContentSize:CGSizeMake(320, self.view.frame.size.height* 1.5)]; } 

Apple Doc

 -(void)viewDidLayoutSubviews 

Llamado para notificar al controlador de vista que su vista acaba de presentar sus subvistas.

Discusión

Cuando los límites cambian para la vista de un controlador de vista, la vista ajusta las posiciones de sus subvistas y luego el sistema llama a este método. Sin embargo, este método que se llama no indica que se hayan ajustado los diseños individuales de las subvistas de la vista. Cada subvista es responsable de ajustar su propio diseño.

Su controlador de vista puede anular este método para realizar cambios después de que la vista establezca sus subvistas. La implementación predeterminada de este método no hace nada.

La forma más fácil / más limpia es configurar contentSize en viewDidAppear para que anule los efectos del diseño automático. Esto no implica agregar vistas aleatorias. Sin embargo, confiar en el orden de carga para que funcione una implementación puede no ser la mejor idea.

Una manera SÚPER fácil de usar AutoLayout con UIScrollViews dentro de Interface Builder:

Paso 1: UIScrollView un UIScrollView

Paso 2: UIView un UIView que sea un elemento secundario de tu vista de desplazamiento, así:

 -UIScrollView ---UIView -----Your other content 

(Llamaremos a esto contentView ).

Paso 3: en el inspector de tamaños, déle a esta vista un alto y ancho (por ejemplo, 320×700).

Paso 4 (usando AutoLayout): contentView restricciones inequívocas desde tu contentView de contentView a su supervista ( UIScrollView ): conecta los 4 bordes (superior, principal, posterior, inferior), y luego dale un ancho y alto definidos para que también se desplace. .

Por ejemplo: si su vista de desplazamiento abarca toda la pantalla, podría darle a su contenido una anchura de [ancho del dispositivo] y una altura de 600; luego establecerá el tamaño del contenido de UIScrollView para que coincida.

O:

Paso 4 (sin utilizar AutoLayout): conecte ambos controles nuevos a su controlador de vista usando IB (ctrl + arrastre desde cada control hasta la implementación de @h @implementation de su controlador). Supongamos que cada uno se llama scrollView y contentView , respectivamente. Debe tener un aspecto como este:

 @interface YourViewController : UIViewController @property (strong, nonatomic) IBOutlet UIScrollView *scrollView; @property (strong, nonatomic) IBOutlet UIView *contentView; @end 

Paso 5 (sin utilizar AutoLayout): en el archivo .h del controlador de vista, agregue (en realidad, anule) el siguiente método:

 -(void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; self.scrollView.contentSize = self.contentView.frame.size; } 

Hay dos problemas aquí. (1) viewDidLoad es demasiado pronto; tienes que esperar hasta que el diseño haya tenido lugar. (2) Si desea utilizar el autolayout con una vista de desplazamiento que proviene de una punta, entonces debe usar restricciones para describir completamente el tamaño de contentSize (y luego no establece el tamaño de contentSize en el código), o si desea establecerlo en código, debe evitar que las restricciones en las subvistas de la vista de desplazamiento dicten el tamaño del contentSize . Parece que le gustaría hacer lo último. Para hacerlo, necesita una UIView que actúe como la única subvista de nivel superior de la vista de desplazamiento, y en el código debe configurarla para que no use la función de ajuste automático, habilite su autoresizingMask y elimine sus otras restricciones externas. Muestro un ejemplo de cómo hacer eso, aquí:

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/ch20p573scrollViewAutoLayout/ch20p573scrollViewAutoLayout/ViewController.m

Pero observe también el siguiente ejemplo, que muestra cómo usar restricciones por completo, en lugar de contentSize .

Usa este código ScrollView setContentSize debe llamarse async en el hilo principal.

 - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; dispatch_async(dispatch_get_main_queue(), ^ { CGRect contentRect = CGRectZero; for (UIView *view in scrollView.subviews) contentRect = CGRectUnion(contentRect, view.frame); contentRect.size.height=contentRect.size.height; scrollView.contentSize = contentRect.size; }); } 

Puede usar estas líneas de código en su archivo * .m

 - (void)viewDidLoad{ [scroll setContentSize:CGSizeMake(320, 800)] ; [scroll setScrollEnabled:TRUE]; [scroll setShowsVerticalScrollIndicator:NO]; [scroll setShowsHorizontalScrollIndicator:YES]; } 

para esto, necesita tomar una propiedad IBOutlet de UIScrollView en su archivo * .h de esta manera:

 IBOutlet UIScrollView *scroll; 

Y conecta esto desde Storyboard.

O,

Puede usar este método en su archivo * .m:

 -(void)viewDidLayoutSubviews { [scroll setContentSize:CGSizeMake(320, self.view.frame.size.height* 1.5)]; // this will pick height automatically from device's height and multiply it with 1.5 } 

Esta solución me funciona en xcode-5, xcode-6, xcode-6.1, xcode-6.2

Establecer el viewDidAppear del contenido en viewDidAppear es crítico.

Pero también tenía una variación de lo que funcionaba en la pantalla de 3,5 pulgadas y la pantalla de 4 pulgadas. La pantalla de 4 pulgadas funcionó, la anterior no. Ambos iOS 7. ¡Bizarre es quedarse corto!

Nunca podría obtener el diseño automático en función de las limitaciones para que funcione. Dado que mi vista ya era una subclase UIScrollView, la resolví anulando setContentView: e ignorando los diseños automáticos zero height setContentSize: message.

 @interface MyView : UIScrollView {} @end @implementation MyView - (void)setContentSize:(CGSize)aSize { if (aSize.height > 0) [super setContentSize:aSize]; } @end 

Solía ​​configurar el uiscrollview programáticamente HASTA que vi el siguiente maravilloso tutorial, paso a paso cómo hacer que uiscrollview y uiview funcionen: https://www.youtube.com/watch?v=PgeNPRBrB18

Después de ver el video, comenzará a gustarme Interface Builder, estoy seguro.

Vota arriba

Si está utilizando AutoLayout una forma muy sencilla de configurar el contentSize de UIScrollView es solo para agregar algo como esto:

 CGFloat contentWidth = YOUR_CONTENT_WIDTH; NSLayoutConstraint *constraintWidth = [NSLayoutConstraint constraintWithItem:self.scrollView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.scrollView attribute:NSLayoutAttributeLeading multiplier:1 constant:contentWidth]; [self.scrollView addConstraint:constraintWidth]; 

Todavía no se desplaza cuando la altura dinámica de las tags supera la altura de visualización.

Hice lo que la respuesta de yuf marcada como correcta dijo que lo hiciera (agregué una vista de contenido a mi vista de desplazamiento y establecí las restricciones delante, detrás, arriba y el mismo ancho desde la vista de contenido a la vista de desplazamiento) pero aun así mi vista era no se desplaza cuando la altura de los controles internos excede la altura de la vista de desplazamiento.

enter image description here

Dentro de mi vista de contenido tengo una imagen y 3 tags debajo. Cada etiqueta ajusta su propia altura en función de la cantidad de texto que hay en ellas (están configuradas en ajuste de palabras y número de líneas = 0 para lograr esto).

El problema que tuve fue que la altura de mi vista de contenido no se ajustaba con la altura dinámica de las tags cuando superaban la altura de la vista de desplazamiento / vista principal.

Para arreglar esto redacté que tenía que establecer la restricción de espacio inferior a contenedor entre mi etiqueta inferior y la vista de contenido y le di un valor de 40 (elegido arbitrariamente para darle un margen agradable en la parte inferior). Esto ahora significa que mi vista de contenido ajusta su altura, de modo que haya un espacio entre la parte inferior de la última etiqueta y ella misma, ¡y se desplaza perfectamente !

¡Hurra!

Probar esto…
agregue todas las restricciones como lo hace para UIView (Vea la captura de pantalla de mi ViewControler en Storyboard )
enter image description here
Ahora el truco comienza. selecciona tu último objeto y selecciona su restricción inferior. (Consulte la captura de pantalla anterior, la restricción inferior del botón de Instagram (línea amarilla)) y cambie el inspector de constante en tamaño, como en la siguiente captura de pantalla.

enter image description here

Requiero constante = 8 pero puede cambiar según sus requisitos. esta constante es el espacio entre la parte inferior de ese botón naranja y el scrollView.

EDITAR

Asegúrate de la jerarquía de tu vista.

0) ViewController.view ( opcional )
1) UIScrollView
2) UIView (Renombrar como “contentView”)
3) UIView (esta vista es su contenido que hará scrollView scroll)

Conseguí que Autolayout funcione para vistas de desplazamiento paginado cuyas páginas ocupan todo el ancho de la pantalla. Las páginas cambian de tamaño automáticamente según el tamaño de la vista de desplazamiento. No he probado esto para vistas de desplazamiento de menor ancho, pero si hago comentarios, creo que debería hacerlo. Dirigido a iOS 9, escribió código en Swift 2, usó una combinación de IB y código personalizado en awakeFromNib .

Pasos:

  • Definir una vista de desplazamiento de pantalla completa.
  • Dentro de la vista de desplazamiento, agregue una UIView (llamé a la mía contentView ) cuyos contentView superior, posterior, inferior y anterior a la vista de desplazamiento son todos cero; la altura es igual a la vista de desplazamiento; pero el ancho es el ancho de la vista de desplazamiento multiplicado por el número de páginas. Si está haciendo esto visualmente, verá que su vista de contenido se extiende más allá de su vista de desplazamiento en Inteface Builder.
  • Para cada “página” dentro de contentView , agregue las reglas de Autolayout para ponerlas una al lado de la otra, pero lo más importante es darle a cada una una restricción para que su ancho sea igual al de la vista de desplazamiento, no a la vista de contenido.

Muestra de código a continuación. embedChildViewController es solo mi método de conveniencia para agregar VCs secundarios; consulte setupLayoutRulesForPages . Tengo exactamente dos páginas, por lo que la función es muy simple, pero puede ampliarla según sus necesidades.

En mi vista controlador:

 override func loadView() { self.view = self.customView } override func viewDidLoad() { super.viewDidLoad() self.embedChildViewController(self.addExpenseVC, toView: self.customView.contentView, fillSuperview: false) self.embedChildViewController(self.addCategoryVC, toView: self.customView.contentView, fillSuperview: false) self.customView.setupLayoutRulesForPages(self.addExpenseVC.view, secondPage: self.addCategoryVC.view) } 

Mi vista personalizada

 class __AMVCView: UIView { @IBOutlet weak var scrollView: UIScrollView! @IBOutlet weak var contentView: UIView! @IBOutlet weak var pageControl: UIPageControl! override func awakeFromNib() { super.awakeFromNib() self.scrollView.pagingEnabled = true self.scrollView.bounces = true self.scrollView.showsHorizontalScrollIndicator = false self.scrollView.showsVerticalScrollIndicator = false self.pageControl.numberOfPages = 2 self.contentView.backgroundColor = UIColor.blueColor() self.scrollView.backgroundColor = UIColor.clearColor() self.backgroundColor = UIColor.blackColor() } func setupLayoutRulesForPages(firstPage: UIView, secondPage: UIView) { guard self.contentView.subviews.contains(firstPage) && self.contentView.subviews.contains(secondPage) else { return } let rules = [ "H:|-0-[firstPage]-0-[secondPage]-0-|", "V:|-0-[firstPage]-0-|", "V:|-0-[secondPage]-0-|" ] let views = [ "firstPage" : firstPage, "secondPage" : secondPage ] let constraints = NSLayoutConstraint.constraintsWithVisualFormatArray(rules, metrics: nil, views: views) UIView.disableAutoresizingMasksInViews(firstPage, secondPage) self.addConstraints(constraints) // Add the width Autolayout rules to the pages. let widthConstraint = NSLayoutConstraint(item: firstPage, attribute: .Width, relatedBy: .Equal, toItem: self.scrollView, attribute: .Width, multiplier: 1, constant: 0) self.addConstraint(widthConstraint) } }