2012-08-27 15 views
8

Cuando llamo al sizeToFit en una de mis vistas, noté que el marco de iOS primero llama a sizeThatFits y luego a layoutSubviews en esa vista. Esto es problemático para mí porque el cálculo en mi sizeThatFits depende de los resultados de mi layoutSubviews. En el siguiente ejemplo, una subvista se ajusta en layoutSubviews y la altura de esta subvista se usa en sizeThatFits. Actualmente mi código no funciona, el orden se invierte.¿Cómo hacer que layoutSubviews sea llamado antes de sizeThatFits?

En viewDidLoad mi punto de vista del controlador:

UIView* header = [[MyHeader alloc] init]; 
[header sizeToFit]; 
self.tableView.tableHeaderView = header; 
[header release]; 

En mi punto de vista:

- (void) layoutSubviews { 
    [super layoutSubviews]; 
    [self.subView sizeToFit]; 
} 

- (CGSize) sizeThatFits:(CGSize)size { 
    return CGSizeMake(
     self.frame.size.width, 
     self.subView.frame.size.height 
    ); 
} 
+0

¿Alguna vez resolvió este problema? –

+0

En su primer código, llame a '[header sizeToFit]' que no hace nada. 'MyTeader''s' sizeThatFits: 'no se reemplaza: > La implementación predeterminada de este método devuelve la porción de tamaño del rectángulo de límites de la vista. – Rivera

Respuesta

0

no puedes cambiar el marco de la subvista en el método -layoutSubviews en lugar del método -sizeThatFits:?

1

¿Ha intentado llamar layoutIfNeeded en la vista para forzar layoutSubviews? A pesar del nombre engañoso, esta es la manera de activar inmediatamente layoutSubviews. Intente llamar esto antes de sizeToFit o sizeThatFits.

6

Desea que su vista siempre haga Lo correcto (tm), sin importar en qué orden llame. Para lograr eso, le sugiero poner su código que calcula la altura deseada para su vista y las subvistas en un método separado. Algo a lo largo de estas líneas:

- (void)updateSubviewDimensions 
{ 
    [self.subview sizeToFit]; 
    // possibly much more code 
} 

- (void) layoutSubviews { 
    [super layoutSubviews]; 
    [self updateSubviewDimensions]; 
} 

- (CGSize) sizeThatFits:(CGSize)size { 
    [self updateSubviewDimensions]; 
    return CGSizeMake(
     self.frame.size.width, 
     self.subView.frame.size.height 
    ); 
} 

De esta manera, no dependen de recordar para llamar a un método determinado antes de llamar sizeToFit, pero su vista siempre hará lo que quiere. Además, su código es menos frágil y más fácil de entender cuando lo mira dentro de unos meses (o si un desarrollador diferente lo analiza).

+0

TL; DR: implementa 'updateConstraints' y llama a' updateSubviewDimensions'. Verbose: no tengo tiempo para una respuesta completa, pero creo que la solución adecuada aquí es implementar updateConstraints. De las pruebas en iOS 8.3, la implementación predeterminada de UIView de systemLayoutConstraintsFittingSize finalmente invoca una llamada a updateConstraints. Esto le da al sistema AL todo lo que necesita para determinar el tamaño, sin tener que establecer las cosas. –

2

Si su diseño sizeThatFits: es preciso, entonces debe forzar un diseño (vea el código a continuación). Pero creo que esto está mal diseñado porque su diseño no está teniendo en cuenta el "tamaño".

- (CGSize) sizeThatFits:(CGSize)size { 

    [self setNeedsLayout]; 
    [self layoutIfNeeded]; 

    return CGSizeMake(
     self.frame.size.width, 
     self.subView.frame.size.height 
    ); 
} 

Un mejor enfoque podría ser el uso de diseño automático para sus subvistas, a continuación, utilizar systemLayoutSizeFittingSize: para determinar el tamaño requerido de la vista (frente a sizeThatFits:)

Si no pueden o no quieren Para usar el diseño automático, debería considerar tener rutas de código separadas para el diseño y el cálculo del diseño.

1

El problema aquí es que las subvistas no tienen dimensiones hasta que se llama a layoutSubviews. Esto es lo mismo que en una celda de vista de tabla personalizada.

Para evitar esto, debe cambiar la lógica o hacer las matemáticas usted mismo para obtener una dimensión explícita sin depender de cosas automáticas.

Cuestiones relacionadas