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;