Agregar una vista (altura) de tamaño dynamic a una UIScrollView con layout automático

Aquí está mi estructura de vistas para esta vista de detalle (aplicación de blog, quiero ver la publicación completa que tiene una altura dinámica dentro de una vista de desplazamiento):

UIView -UIScrollView -SinglePostView (custom view) -Title -Subtitle -Content 

Normalmente, para agregar una 'vista de publicación única' a una UIView simplemente instancio, aliméntelo en mi object de publicación y luego agrego una restricción única que fija el ancho de singlePostView a la vista de supervisión, momento en el que las cosas se configuran bien. Sin embargo, cuando bash agregarlo a una vista de desplazamiento, no aparece ni se desplaza.

 UIScrollView *scrollView = [[UIScrollView alloc] init]; [self.view addSubview:scrollView]; NOBSinglePostView *singlePost = [[NOBSinglePostView alloc] initWithPost:self.post]; [scrollView addSubview:singlePost]; singlePost.translatesAutoresizingMaskIntoConstraints = NO; scrollView.translatesAutoresizingMaskIntoConstraints = NO; NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(scrollView,singlePost); [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]]; [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[singlePost]|" options:0 metrics: 0 views:viewsDictionary]]; 

En la estructura que está presentando, utilizando AutoLayout, contentSize de su UIScrollView está impulsado por el contenido intrinsicContentSize de sus subvistas, aquí su SinglePostView .

El problema es que SinglePostView es una subclass de UIView , su intrinsicContentSize siempre es CGSizeZero cuando se considera por sí mismo. Lo que debe hacer es hacer que el contenido intrinsicContentSize de su SinglePostView dependa del contenido intrinsicContentSize de sus subvistas.

Entonces, debido a que las sub-vistas de su SinglePostView son UILabels , y debido a que el UILabel intrinsicContentSize un UILabel es el tamaño más pequeño que necesita para mostrar su contenido, el contenido intrinsicContentSize su SinglePostView será igual a la sum de sus subíndices intrinsicContentSizes , es decir, el tamaño total Necesito mostrar el contenido de las tres tags.

Aquí es cómo hacerlo.

Paso 1: Eliminar todas las restricciones establecidas automáticamente.

Primero, como lo hizo parcialmente, debe eliminar todas las restricciones establecidas automáticamente por el sistema.

Suponiendo que no tiene ninguna restricción establecida en su guión gráfico o XIB (o incluso si no tiene uno de estos), simplemente haga lo siguiente:

 scrollView.translatesAutoresizingMaskIntoConstraints = NO; singlePost.translatesAutoresizingMaskIntoConstraints = NO; titleLabel.translatesAutoresizingMaskIntoConstraints = NO; subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO; contentLabel.translatesAutoresizingMaskIntoConstraints = NO; 

Ahora tiene una list clara y puede comenzar a establecer sus propias limitaciones.

Paso 2: scrollView el scrollView

Primero, creamos, como lo hizo, el dictionary de references de vistas para que AutoLayout lo use:

 NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, singlePost, titleLabel, subtitleLabel, contentLabel); 

Entonces, también como ya lo hiciste, limitemos la vista de desplazamiento para que sea del tamaño de su supervisión:

 [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[scrollView]-0-|" options:0 metrics:0 views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[scrollView]-0-|" options:0 metrics:0 views:views]]; 

Paso 3: Restringir el SinglePostView para impulsar el contentSize scrollView .

Para que este paso sea claro, debe comprender que cada set de restricciones entre una UIScrollView y sus subviews realmente cambiará el contentSize de la UIScrollView , no sus bounds reales. Por ejemplo, si restringe un UIImageView a los bordes de su UIScrollView primario y luego coloca una image dos veces mayor que el UIScrollView dentro del UIImageView , su image no se contraerá, es el UIImageView que tomará el tamaño de su image y se puede desplazar dentro de UIScrollView .

Entonces, aquí tienes lo que debes establecer aquí:

 [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[singlePost]-0-|" options:0 metrics:0 views:views]]; [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[singlePost]-0-|" options:0 metrics:0 views:views]]; [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:singlePost attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeWidth multiplier:1.0f constant:0.0f]]; 

Las primeras dos restricciones son bastante obvias. El tercero, sin embargo, está aquí porque, para que tus UILabels muestren su contenido correctamente y aún sean legibles, probablemente querrás que sean multilíneas y que el desplazamiento sea vertical, no horizontal. Es por eso que establece que el width su SinglePostView sea ​​el mismo que el de su scrollView . De esta forma, evita que su contentSize.width scrollView sea ​​mayor que su bounds.width .

Paso 4: UILabels tus UILabels para "empujar" los límites de tu SinglePostView

Cuarto y último paso, ahora necesita establecer restricciones en las subvenciones de su SinglePostView , de modo que obtenga un Contenido intrinsicContentSize de ellas.

Así es como lo hace (implementación más simple, sin márgenes, una label después de la otra verticalmente):

 [singlePost addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[titleLabel]-0-|" options:0 metrics:0 views:views]]; [singlePost addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[subtitleLabel]-0-|" options:0 metrics:0 views:views]]; [singlePost addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[contentLabel]-0-|" options:0 metrics:0 views:views]]; [singlePost addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[titleLabel]-0-[subtitleLabel]-[contentLabel]-0-|" options:0 metrics:0 views:views]]; 

Y con eso debes terminar.

Un último consejo, definitivamente deberías search en UIStoryboard para hacer este tipo de cosas. Es mucho más simple y visual.

Espero que esto ayude,

PS: si quieres, puedo tomarme un time y presionar un proyecto usando tanto UIStoryboard como el Visual Format Language en Github. Solo dime si necesitas uno.

Buena suerte.

en layout automático

El marco de scrollview se decide por las restricciones entre scrollview y superview de scrollview . scrollview de scrollview se decide por las restricciones entre scrollview y scrollview de scrollview .

debe establecer el tamaño de singlePostView . ScrollView calcula contentSize desde él. (debe agregar explícitamente las restricciones de tamaño)

 CGFloat heightOfSinglePostView = calculate.. [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[singlePost(heightOfSinglePostView)]|" options:0 metrics: 0 views:viewsDictionary]];