Swift - CGAffineTransform 旋转
Swift - CGAffineTransform rotation
我有一个 UIImageView
可以在 draw
函数中轮换。
public var progress: CGFloat = 0 {
didSet {
setNeedsDisplay()
}
}
override public func draw(_ rect: CGRect) {
rotateIcon(by: progress)
}
private func rotateIcon(by angle: CGFloat) {
if imageView == nil {
imageView = UIImageView(image: UIImage(named: "bt_info"))
imageView?.center = center
imageView?.frame.size = CGSize(width: 24.0, height: 24.0)
addSubview(imageView!)
}
imageView?.transform = CGAffineTransform(rotationAngle: angle)
}
下面是上面代码片段的附加输出。
当我设置框架大小时,imageView
旋转时会收缩和扩展。我想在 imageView
旋转时保持大小。我错过了什么?
好的 - 您在问题中发布的代码与您的 Dropbox 项目中的代码不匹配...
在您的项目中,您这样做:
private func rotateScannerIcon(by angle: CGFloat) {
if testView == nil {
testView = UIView()
testView?.backgroundColor = .red
addSubview(testView!)
}
let centerPoint = CGPoint(x: bounds.midX, y: bounds.midY)
testView?.center = centerPoint
testView?.frame.size = CGSize(width: 24.0, height: 24.0)
testView?.transform = CGAffineTransform(rotationAngle: angle)
}
使用该代码,您将在应用旋转变换后更改帧大小...实际视图是不再是“正方形”。
如果您在“创建”块中移动位置/尺寸代码:
private func rotateScannerIcon(by angle: CGFloat) {
if testView == nil {
testView = UIView()
testView?.backgroundColor = .red
addSubview(testView!)
let centerPoint = CGPoint(x: bounds.midX, y: bounds.midY)
testView?.center = centerPoint
testView?.frame.size = CGSize(width: 24.0, height: 24.0)
}
testView?.transform = CGAffineTransform(rotationAngle: angle)
}
帧的“挤压”不再发生。
不过,覆盖 draw()
可能不是最好的方法。这主要是在 UIKit 视图更新不足以处理布局时完成的——例如在路径上使用 stroke/fill 时。
因此,我建议进行一些更改。
当自定义视图 subclass 初始化时创建你的子视图(UIView
或 UIImageView
或其他),并且 size/position 它带有 auto-layout 约束.
然后,当您更新 progress
属性 时,应用旋转变换。
例如,这是您的 TestView
class:
的修改版本
public class TestView: UIView {
public var progress: CGFloat = 0 {
didSet {
rotateScannerIcon(by: (progress * CGFloat(Double.pi)))
}
}
internal var testView: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
// create the view (or image view)
testView = UIView()
testView.backgroundColor = .red
// add it to self
addSubview(testView)
// let's use auto-layout constraints
testView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
// constrain the view to 24 x 24, centered in self
testView.widthAnchor.constraint(equalToConstant: 24.0),
testView.heightAnchor.constraint(equalTo: testView.widthAnchor),
testView.centerXAnchor.constraint(equalTo: centerXAnchor),
testView.centerYAnchor.constraint(equalTo: centerYAnchor),
])
}
private func rotateScannerIcon(by angle: CGFloat) {
testView.transform = CGAffineTransform(rotationAngle: angle)
}
}
我有一个 UIImageView
可以在 draw
函数中轮换。
public var progress: CGFloat = 0 {
didSet {
setNeedsDisplay()
}
}
override public func draw(_ rect: CGRect) {
rotateIcon(by: progress)
}
private func rotateIcon(by angle: CGFloat) {
if imageView == nil {
imageView = UIImageView(image: UIImage(named: "bt_info"))
imageView?.center = center
imageView?.frame.size = CGSize(width: 24.0, height: 24.0)
addSubview(imageView!)
}
imageView?.transform = CGAffineTransform(rotationAngle: angle)
}
下面是上面代码片段的附加输出。
当我设置框架大小时,imageView
旋转时会收缩和扩展。我想在 imageView
旋转时保持大小。我错过了什么?
好的 - 您在问题中发布的代码与您的 Dropbox 项目中的代码不匹配...
在您的项目中,您这样做:
private func rotateScannerIcon(by angle: CGFloat) {
if testView == nil {
testView = UIView()
testView?.backgroundColor = .red
addSubview(testView!)
}
let centerPoint = CGPoint(x: bounds.midX, y: bounds.midY)
testView?.center = centerPoint
testView?.frame.size = CGSize(width: 24.0, height: 24.0)
testView?.transform = CGAffineTransform(rotationAngle: angle)
}
使用该代码,您将在应用旋转变换后更改帧大小...实际视图是不再是“正方形”。
如果您在“创建”块中移动位置/尺寸代码:
private func rotateScannerIcon(by angle: CGFloat) {
if testView == nil {
testView = UIView()
testView?.backgroundColor = .red
addSubview(testView!)
let centerPoint = CGPoint(x: bounds.midX, y: bounds.midY)
testView?.center = centerPoint
testView?.frame.size = CGSize(width: 24.0, height: 24.0)
}
testView?.transform = CGAffineTransform(rotationAngle: angle)
}
帧的“挤压”不再发生。
不过,覆盖 draw()
可能不是最好的方法。这主要是在 UIKit 视图更新不足以处理布局时完成的——例如在路径上使用 stroke/fill 时。
因此,我建议进行一些更改。
当自定义视图 subclass 初始化时创建你的子视图(UIView
或 UIImageView
或其他),并且 size/position 它带有 auto-layout 约束.
然后,当您更新 progress
属性 时,应用旋转变换。
例如,这是您的 TestView
class:
public class TestView: UIView {
public var progress: CGFloat = 0 {
didSet {
rotateScannerIcon(by: (progress * CGFloat(Double.pi)))
}
}
internal var testView: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
// create the view (or image view)
testView = UIView()
testView.backgroundColor = .red
// add it to self
addSubview(testView)
// let's use auto-layout constraints
testView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
// constrain the view to 24 x 24, centered in self
testView.widthAnchor.constraint(equalToConstant: 24.0),
testView.heightAnchor.constraint(equalTo: testView.widthAnchor),
testView.centerXAnchor.constraint(equalTo: centerXAnchor),
testView.centerYAnchor.constraint(equalTo: centerYAnchor),
])
}
private func rotateScannerIcon(by angle: CGFloat) {
testView.transform = CGAffineTransform(rotationAngle: angle)
}
}