2010-04-22 19 views
14

Me sorprendió no encontrar una respuesta a esta pregunta, tal vez es algo muy sencillo de alguna manera por alto:Obtener tamaño de UIView después solicitando CGAffineTransform

Cómo obtener el tamaño real de un UIView después de aplicar un CGAffineTransform a ¿eso?

por ejemplo.

Mi UIView tiene un tamaño de 300 x 200, aplico una transformación de escala digamos factor 2 horizontal y vertical, por lo que UIView ahora toma 600 x 400 en la pantalla, pero sus límites y sus límites siguen siendo de un tamaño de 300 x 200 ... ¿dónde encuentro el tamaño real de UIView?

ps. Olvidé mencionar que también quiero rotar la vista. Si aplico solo escalar CGSizeApplyAffineTransform funciona muy bien, pero cuando también hay rotación, no funciona correctamente.

Editar: drawnonward me señaló en la dirección correcta, sólo refinado un poco el código para compilar y aquí está:

UIView* view = (your view being transformed); 
CGAffineTransform trans = (view.transform or create a new transformation); 

CGRect rect = [view bounds]; 
CGMutablePathRef path = CGPathCreateMutable(); 
rect.origin = CGPointZero; 
CGPathAddRect(path , &trans , rect); 
rect = CGPathGetBoundingBox(path); 
CGPathRelease(path); 

Ahora contiene rect.size las dimensiones de la vista de la transformación aplicados Gracias nuevamente a drawonward

Respuesta

11

[myView frame] devuelve el marco de la vista tal como lo ve el elemento principal, para el diseño y los tamaños relativos. [myView bounds] devuelve los límites de la vista como se ve por sí mismo, para dibujar. Si tiene transformadas aplicadas a múltiples vistas, puede usar convertRect: desde o hacia una vista.

Editar:

Quizás algo como esto.

CGRect rect = [view bounds]; 
CGPathRef path = CGPathCreateMutable(); 
rect.origin = CGPointZero; 
CGPathAddRect(rect , [view transform]); 
rect = CGPathGetBoundingBox(path); 
CGPathRelease(path); 

El uso [view center] para encontrar la posición en el supervista.

+1

Aquí está la documentación sobre "marco" de los documentos de Apple: Advertencia: Si la propiedad de transformación no es la transformación de identidad, el valor de esta propiedad no está definido y, por lo tanto, ser ignorado. Entonces, frame está fuera de cuestión cuando se aplica la transformación. Y "límites" siempre devuelve el tamaño original –

+0

¡De hecho! Argh, esta biblioteca de funciones de la que siempre me olvido, CGPathGetBoundingBox fue el truco. Edité la pregunta con el código de trabajo, muchas gracias, hombre –

+0

También tenga en cuenta que se supone que la propiedad del centro funciona, incluso con transformaciones que no sean de identidad. – Olie

2

Use CGSizeApplyAffineTransform(size, transform) y devolverá un tamaño transformado. Hay funciones similares CGPoint y CGRect también.

+0

Eso no funciona correctamente cuando CGSizeApplyAffineTransform incluye también la rotación, pero de lo contrario tiene razón en los casos en los que solo se aplica escala. (Mi error no incluí también la rotación en mi pregunta) –

2

más simple: Se aplica una vista con (límites) tamaño s para que transforman tr tiene tamaño resultante:

CGSizeMake(s.width*hypotf(tr.a, tr.b), s.height*hypotf(tr.c, tr.d)) 

Sin embargo, si supervista de vista o cualquier vista antepasado tenga cualquier no-unidad de transformada de aplicarse, este tamaño tiene poco sentido en términos absolutos.

Si desea el tamaño absoluto de una vista en coordenadas de ventana después de aplicar cualquier transformación arbitraria a esa vista o sus supervistas, primero debe calcular la matriz de transformación absoluta componiendo toda la transformación de vista hasta la ventana raíz, y luego aplica la fórmula anterior al resultado.

33

que utilizo:

CGRect transformedBounds = CGRectApplyAffineTransform(view.bounds, view.transform); 
+0

creo que solo "view.bounds" sería una mejor respuesta. ¿Por qué estás transformando los límites aquí en lugar de simplemente tomar el tamaño del marco? –

0

Pero se aplica una rotación a transformar, que no conseguir tamaño correcto por CGPathGetBoundingBox.

2

Pregunta anterior, pero me topé aquí, después de buscar una solución y toneladas de intentos.Fue simple;

view.layer.frame tiene todas las transformaciones aplicadas y obtendrá el tamaño de view.layer.frame.size fácilmente.

- por debajo de aquí no es una respuesta a esta pregunta - -

Y para mi problema, yo estaba tratando de calcular un nuevo valor center después de cambiar layer.anchorPoint de mi vista girada, por lo que no se mueve . Y finalmente lo hizo así;

CGPoint topLeft = [self.superview convertPoint:CGPointMake(0, 0) fromView:self]; 
self.layer.anchorPoint = CGPointMake(0, 0); 
self.center = topLeft; 

para inversa

CGPoint center = [self.superview convertPoint:CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2) fromView:self]; 
self.layer.anchorPoint = CGPointMake(.5, .5); 
self.center = center; 

finalmente.

Cuestiones relacionadas