objective-c uiview cgaffinetransform

objective c - Obtener el tamaño de UIView después de aplicar CGAffineTransform



objective-c (6)

Me sorprendió no encontrar una respuesta a esta pregunta, tal vez sea algo muy simple que de alguna manera pase por alto:

¿Cómo obtener el tamaño real de una UIView después de aplicarle un CGAffineTransform?

p.ej.

mi UIView tiene un tamaño de 300 x 200, aplico una transformación de escala, digamos factor 2 tanto horizontal como vertical, por lo que la UIView ahora toma 600 x 400 en la pantalla, pero sus límites y los límites de su capa siguen regresando a un tamaño de 300 x 200 ... ¿Dónde encuentro el tamaño real de UIView?

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

Edit: drawnonward me señaló en la dirección correcta, simplemente refiné 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 rect.size contiene las dimensiones de la vista con la transformación aplicada Gracias de nuevo a drawnonward


Más simple: una vista con el tamaño s (límites) a la que se aplica la transformación tr tiene el tamaño resultante:

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

Sin embargo, si la vista supervisada de la vista o cualquier vista ancestral tiene aplicada alguna transformación no unitaria, este tamaño tiene poco sentido en términos absolutos.

Si desea que el tamaño absoluto de una vista en las coordenadas de la ventana después de una transformación arbitraria se haya aplicado a esa vista o sus superviews, primero debe calcular la matriz de transformación absoluta al componer toda la transformación de la vista hasta la ventana raíz, y luego aplicar la Fórmula anterior al resultado.


Pero si aplicas una transformación rotativa, CGPathGetBoundingBox no obtiene el tamaño correcto.


Pregunta antigua, pero encontré aquí, después de buscar una solución y un montón de intentos. Era simple;

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

- aquí abajo no es una respuesta a esta pregunta -

Y para mi problema, estaba tratando de calcular el nuevo valor center después de cambiar layer.anchorPoint de mi vista rotada, para que no se mueva. 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 revertir

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.


Utilice CGSizeApplyAffineTransform(size, transform) y devolverá un tamaño transformado. También hay funciones CGPoint y CGRect similares.


Yo uso esto en el Objetivo C:

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

o en Swift 4:

let transformedBounds = view.bounds.applying(view.transform)


[myView frame] devuelve el marco de la vista como lo ve el padre, 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 el dibujo. Si tiene transformadas aplicadas a varias vistas, puede usar convertRect: hacia o desde una vista.

Editar:

Tal vez 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 la vista de supervisión.