ios swift uiview rotation subclass

ios - Rotación de una vista en diseño



swift uiview (2)

El problema con el código en la pregunta parece ser que las transformaciones se siguen agregando entre sí. Para solucionar esto, la solución es restablecer las transformaciones cada vez, es decir, configurarlo en la transformación de identidad.

rotationView.transform = CGAffineTransformIdentity

Aquí hay una implementación parcial que muestra las partes clave.

import UIKit @IBDesignable class UIVerticalTextView: UIView { var textView = UITextView() let rotationView = UIView() var underlyingTextView: UITextView { get { return textView } set { textView = newValue } } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override init(frame: CGRect){ super.init(frame: frame) self.setup() } override func awakeFromNib() { super.awakeFromNib() self.setup() } func setup() { rotationView.backgroundColor = UIColor.redColor() textView.backgroundColor = UIColor.yellowColor() self.addSubview(rotationView) rotationView.addSubview(textView) // could also do this with auto layout constraints textView.frame = rotationView.bounds } override func layoutSubviews() { super.layoutSubviews() rotationView.transform = CGAffineTransformIdentity // *** key line *** rotationView.frame = CGRect(origin: CGPointZero, size: CGSize(width: self.bounds.height, height: self.bounds.width)) rotationView.transform = translateRotateFlip() } func translateRotateFlip() -> CGAffineTransform { var transform = CGAffineTransformIdentity // translate to new center transform = CGAffineTransformTranslate(transform, (self.bounds.width / 2)-(self.bounds.height / 2), (self.bounds.height / 2)-(self.bounds.width / 2)) // rotate counterclockwise around center transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2)) // flip vertically transform = CGAffineTransformScale(transform, -1, 1) return transform } }

Es probable que mi implementación más reciente se encuentre en este enlace de github .

Antecedentes y objetivo

Objetivo: quiero rotar y voltear un UITextView . ( Por qué: mira mi pregunta anterior )

Problema: si realizo la transformación directamente en UITextView , el diseño del texto se estropea por algún motivo desconocido.

Solución: UITextView en un contenedor UIView y luego realice la transformación en el contenedor.

Nuevo problema: el diseño automático (o cualquier tipo de diseño) en la vista girada se convierte en un gran dolor de cabeza .

Solución propuesta: haga una subclase de UIView que actúe como un contenedor adicional para la UIView girada y volteada. El diseño automático debería funcionar en esta vista personalizada.

Problema actual

Funciona cuando todo aparece por primera vez ( UITextView tiene fondo amarillo):

pero cuando hay un cambio de orientación, sucede lo siguiente (el azul es el fondo UIView subclasificado, establecido en IB):

Si deshabilito la línea rotationView.addSubview(textView) , la vista del contenedor de rotación (rojo) se reposiciona bien, incluso en un cambio de orientación:

Entonces, el problema debe estar relacionado con el lugar donde estoy agregando el UITextView . ¿Pero cómo lo hago?

Código

class MongolTextView: UIView { // properties var rotationView: UIView! var textView: UITextView! // This method gets called if you create the view in the Interface Builder required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } // This method gets called if you create the view in code override init(frame: CGRect){ super.init(frame: frame) self.setup() } override func awakeFromNib() { super.awakeFromNib() self.setup() } func setup() { rotationView = UIView(frame: self.frame) rotationView.backgroundColor = UIColor.redColor() self.addSubview(rotationView) textView = UITextView(frame: CGRectZero) textView.backgroundColor = UIColor.yellowColor() textView.text = "This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text This is some text " } override func layoutSubviews() { super.layoutSubviews() // set the size of the rotation container view let width = self.bounds.width let height = self.bounds.height rotationView.frame = CGRect(origin: CGPoint(x: CGFloat(0), y: CGFloat(0)), size: CGSize(width: height, height: width)) textView.frame = rotationView.bounds // Problem lines here??? rotationView.addSubview(textView) // Problem lines here??? // rotate, translate, and flip the container view var rotation = CGAffineTransformMakeRotation(CGFloat(-M_PI_2)) // the following translation repositions the top left corner at the origin of the superview var translation = CGAffineTransformMakeTranslation((rotationView.bounds.height / 2)-(rotationView.bounds.width / 2), (rotationView.bounds.width / 2)-(rotationView.bounds.height / 2)) var rotationAndTranslation = CGAffineTransformConcat(rotation, translation) var transformPlusScale = CGAffineTransformScale(rotationAndTranslation, CGFloat(-1), CGFloat(1)) rotationView.transform = transformPlusScale } }

Si no puedo hacer que esto funcione ...

Aunque actualmente me he encontrado con un muro aquí, mi próximo plan es anular drawRect() para hacer las transformaciones. Sin embargo, esta no es mi primera opción, porque se supone que el rendimiento se ralentiza al hacer esto.


En modo de depuración, verifique su ancho y alto. Supongo que son iguales después y antes de la rotación. De esta manera, se esperan sus capturas de pantalla.

Lo segundo es que aplicas la transformación dos veces.

tiene vista de rotación -> aplica la transformación -> cambia el marco en la rotación del teléfono -> la transformación anterior todavía se aplica -> luego aplica otra transformación. Quizás tu respuesta esté aquí.

EDITAR:

Posibles soluciones:

Puedes detectar la orientación de bruja que tienes

UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; if(orientation == 0) //Default orientation //UI is in Default (Portrait) -- this is really a just a failsafe. else if(orientation == UIInterfaceOrientationPortrait) //Do something if the orientation is in Portrait else if(orientation == UIInterfaceOrientationLandscapeLeft) // Do something if Left else if(orientation == UIInterfaceOrientationLandscapeRight)

y luego decidí cómo manejar esto.

Si la orientación es vertical de lo que tomas

width = self.bound.size.width; height = self.bound.size.height;

si no

height = self.bound.size.width; width = self.bound.size.height;