La relación de aspecto de UIView confunde systemLayoutSizeFittingSize

Bien, otro problema de altura dinámica de UITableViewCell, pero con un pequeño giro. Desafortunadamente, no puedo saltar a iOS 8 solo cuando se lance, de lo contrario el problema se resolverá. Necesito iOS> = 7.1.

Estoy tratando de lograr una celda con dos imágenes en la parte superior de la celda, una label de título debajo de ellas y una label de descripción debajo de eso. Sé que las dos imágenes superiores serán cuadradas y, por lo tanto, quiero que tengan el mismo tamaño y que mantengan la relación de aspecto cuadrada, pero cambien de tamaño cuando el tamaño de la pantalla varía (como cambio de orientación o dispositivo diferente).

Una image que podría ayudar con la visualización (no se puede include debido a la repetición. No importa los colors, ayuda de visualización): http://i.stack.imgur.com/kOhkl.png

Observe la brecha después del último text, que se supone que no debe estar allí.

Implementé la altura dinámica en la aplicación anterior de acuerdo con: Uso del layout automático en UITableView para layouts de celdas dinámicas y alturas de filas variables (con éxito), y también usé el mismo método ahora.

He configurado las restricciones utilizando tanto storyboards como programáticamente, pero sin éxito.

Aquí está el pateador sin embargo. Al llamar:

CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; 

En:

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 

el valor de la altura es mucho más grande que la altura al leer:

 cell.contentView.frame 

Otro problema es que si elimino las restricciones de relación de aspecto en las imágenes y solo las cambia a una restricción de altura explícita, funciona bien.

Para cualquiera que esté dispuesto a ayudar, preparé un proyecto de muestra realmente sencillo que ilustra el problema: https://github.com/alefr/DynamicTableCellHeight

Está configurado para utilizar storyboards para restricciones y hay una twig adicional: ExplicitHeightConstraint que no hace más que cambiar la restricción de ración de aspecto a una restricción de altura para las imágenes.

** Entonces, la pregunta es: ** ¿Alguien puede ver algo mal con las restricciones que lo hacen confundir los cálculos de altura, o alguien tiene alguna sugerencia alternativa para get el resultado deseado? (Aunque me gustaría usar el layout automático para las vistas).

Hay algunas limitaciones en las obras (aunque nada realmente sofisticado), así que creo que es más fácil mirar en el storyboard provisto (github link) que explicándolos explícitamente aquí. Pero si alguien se imagina que también puedo hacer eso. Los cálculos de altura estimados parecen:

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { // Don't care about memory leaks now: DynamicTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"dynamicCell"]; [self populateCell:cell withContent:self.tableData[indexPath.row]]; // Make sure the constraints have been set up for this cell, since it may have just been created from scratch. // Use the following lines, assuming you are setting up constraints from within the cell's updateConstraints method: [cell setNeedsUpdateConstraints]; [cell updateConstraintsIfNeeded]; // Set the width of the cell to match the width of the table view. This is important so that we'll get the // correct cell height for different table view widths if the cell's height depends on its width (due to // multi-line UILabels word wrapping, etc). We don't need to do this above in -[tableView:cellForRowAtIndexPath] // because it happens automatically when the cell is used in the table view. // Also note, the final width of the cell may not be the width of the table view in some cases, for example when a // section index is displayed along the right side of the table view. You must account for the networkinguced cell width. cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds)); // Do the layout pass on the cell, which will calculate the frames for all the views based on the constraints. // (Note that you must set the prefernetworkingMaxLayoutWidth on multi-line UILabels inside the -[layoutSubviews] method // of the UITableViewCell subclass, or do it manually at this point before the below 2 lines!) [cell setNeedsLayout]; [cell layoutIfNeeded]; // Get the actual height requinetworking for the cell's contentView CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; // So we can read debug values CGRect contentFrame = cell.contentView.frame; CGRect firstImageFrame = cell.firstArtwork.frame; CGRect secondImageFrame = cell.secondArtwork.frame; CGRect nameFrame = cell.name.frame; CGRect numArtworksFrame = cell.numArtworks.frame; // Add an extra point to the height to account for the cell separator, which is added between the bottom // of the cell's contentView and the bottom of the table view cell. height += 1.0f; return height; } - (void)populateCell:(DynamicTableViewCell*)cell withContent:(DynamicContent*)content { cell.firstArtwork.image = content.firstImage; cell.secondArtwork.image = content.secondImage; cell.name.text = content.name; cell.numArtworks.text = [NSString stringWithFormat:@"%@ artworks", content.numImages]; } 

Gracias

Tengo la misma situación, lo resolví para anular la function systemLayoutSizeFittingSize en la celda dada y replace la restricción aspectRation a una restricción de altura. En el siguiente ejemplo, se agrega mediaPlayerAspectRationConstraint a la vista durante el ciclo de vida de la vista y se mediaPlayerHeightContraint para determinar la altura correcta de la celda (ver el código a continuación).

Y después de eso usé el

 CGFloat height = [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; 

en lugar de [cell.contentView systemLayoutSizeFittingSize:] .

 - (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize { self.mediaPlayerHeightContraint.constant = CGRectGetHeight(self.experienceMedia.frame); //Lets replace it with an exact height constraint (workaround). //To remove the Unable to simultaneously satisfy constraints. exceptions [self.contentView layoutIfNeeded]; [self.experienceMedia removeConstraint:self.mediaPlayerAspectRationConstraint]; [self.experienceMedia addConstraint:self.mediaPlayerHeightContraint]; [self setNeedsUpdateConstraints]; CGSize res = [self.contentView systemLayoutSizeFittingSize:targetSize]; [self.contentView layoutIfNeeded]; [self.experienceMedia removeConstraint:self.mediaPlayerHeightContraint]; [self.experienceMedia addConstraint:self.mediaPlayerAspectRationConstraint]; [self setNeedsUpdateConstraints]; return res; }