在 layoutSubviews 中旋转视图
Rotating a view in layoutSubviews
背景和目标
目标:我想旋转翻转一个UITextView
。 (为什么:看我的previous question)
问题: 如果我直接在 UITextView
上进行转换,文本布局会由于某种未知原因而变得混乱。
解决方法:将UITextView
放入UIView
容器中,然后在容器上进行变换
新问题: 旋转视图上的自动布局(或任何类型的布局)变为 a major headache。
建议的解决方案: 创建一个 UIView
的子类,作为旋转和翻转的附加容器 UIView
。自动布局应该在这个自定义视图上工作。
当前问题
当所有内容首次出现时有效(UITextView
背景为黄色):
但是当方向发生变化时,会发生以下情况(蓝色是子类 UIView
背景,在 IB 中设置):
如果我禁用 rotationView.addSubview(textView)
行,那么旋转容器视图(红色)会自动重新定位,即使在方向改变时也是如此:
所以问题一定出在我添加 UITextView
的位置。但是我该怎么做呢?
代码
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
}
}
如果我不能让它工作...
虽然我目前 运行 在这里靠墙,但我的下一个计划是覆盖 drawRect()
来进行转换。不过,这不是我的第一选择,因为据说这样做会降低性能。
在调试模式下检查您的宽度和高度。我猜他们在旋转前后是一样的。这样您的屏幕截图将是预期的。
第二件事是你应用了两次转换。
你有旋转视图 -> 你应用变换 -> 你在 phone 旋转时改变框架 -> 以前的变换仍然应用 -> 然后你应用另一个变换。
或许你的答案就在这里。
编辑:
可能的解决方案:
您可以检测 您的方向
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)
然后决定如何处理。
如果方向是纵向而不是你
width = self.bound.size.width;
height = self.bound.size.height;
如果不是
height = self.bound.size.width;
width = self.bound.size.height;
问题中代码的问题似乎是转换不断地相互添加。为了解决这个问题,解决方案是每次都重新设置转换,即将其设置为身份转换。
rotationView.transform = CGAffineTransformIdentity
这是显示关键部分的部分实现。
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
}
}
我最近的实现最有可能在 this github link 中找到。
背景和目标
目标:我想旋转翻转一个UITextView
。 (为什么:看我的previous question)
问题: 如果我直接在 UITextView
上进行转换,文本布局会由于某种未知原因而变得混乱。
解决方法:将UITextView
放入UIView
容器中,然后在容器上进行变换
新问题: 旋转视图上的自动布局(或任何类型的布局)变为 a major headache。
建议的解决方案: 创建一个 UIView
的子类,作为旋转和翻转的附加容器 UIView
。自动布局应该在这个自定义视图上工作。
当前问题
当所有内容首次出现时有效(UITextView
背景为黄色):
但是当方向发生变化时,会发生以下情况(蓝色是子类 UIView
背景,在 IB 中设置):
如果我禁用 rotationView.addSubview(textView)
行,那么旋转容器视图(红色)会自动重新定位,即使在方向改变时也是如此:
所以问题一定出在我添加 UITextView
的位置。但是我该怎么做呢?
代码
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
}
}
如果我不能让它工作...
虽然我目前 运行 在这里靠墙,但我的下一个计划是覆盖 drawRect()
来进行转换。不过,这不是我的第一选择,因为据说这样做会降低性能。
在调试模式下检查您的宽度和高度。我猜他们在旋转前后是一样的。这样您的屏幕截图将是预期的。
第二件事是你应用了两次转换。
你有旋转视图 -> 你应用变换 -> 你在 phone 旋转时改变框架 -> 以前的变换仍然应用 -> 然后你应用另一个变换。 或许你的答案就在这里。
编辑:
可能的解决方案:
您可以检测 您的方向
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)
然后决定如何处理。
如果方向是纵向而不是你
width = self.bound.size.width;
height = self.bound.size.height;
如果不是
height = self.bound.size.width;
width = self.bound.size.height;
问题中代码的问题似乎是转换不断地相互添加。为了解决这个问题,解决方案是每次都重新设置转换,即将其设置为身份转换。
rotationView.transform = CGAffineTransformIdentity
这是显示关键部分的部分实现。
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
}
}
我最近的实现最有可能在 this github link 中找到。