CGAffineTransform 旋转导致定义 SnapKit 值时宽度和高度之间的切换
CGAffineTransform rotation causes a switch between width and height when defining SnapKit values
我用SnapKit比较习惯,但是不知道怎么解决这个问题
这是我现在的 UI 的样子:
为了实现这一目标,我这样做:
override func viewDidLoad() {
super.viewDidLoad()
regionsPicker.snp.makeConstraints { (make) in
make.centerX.equalToSuperview()
make.height.equalToSuperview() // since we rotate (this is the width)
make.top.equalTo(regionsLabel.snp.bottom).offset(15)
make.width.equalTo(100)
}
rotationAngle = -90 * (.pi/180)
regionsPicker.transform = CGAffineTransform(rotationAngle: rotationAngle)
}
如上所示,我正在尝试将标签的底部与选择器视图的顶部对齐。但是由于我正在旋转我的视图,使高度等于超级视图,所以它创建了这个巨大的 space。
我看到 建议在这个特定情况下使用自动布局,或者,我也可以使用集合视图,但我很想知道是否有针对此的 SnapKit 解决方案和
感谢您的帮助。
问题出在Apple文档中transform的这部分描述:https://developer.apple.com/documentation/uikit/uiview/1622459-transform
In iOS 8.0 and later, the transform property does not affect Auto Layout. Auto layout calculates a view’s alignment rectangle based on its untransformed frame.
So, when you change the text of the label, your constraints are related to the untransformed frame.
因此,您将 pickerView 的 height 设置为视图的 height。然后旋转它,它会 出现 以显示您想要的外观。
不过,如果您使用 Debug View Hierarchy
,您会看到 pickerView 现在延伸到其 superView 的前缘和后缘之外。
您还会看到 pickerView 的 bounds 的宽度和高度 - 100 x 667
(在 iPhone 8) - 这不是你所期望的。
当视图大小发生变化时(例如在设备旋转时),这也会出现问题。
这是一个示例方法:
import UIKit
class ViewController: UIViewController {
let regionsLabel: UILabel = {
let v = UILabel()
v.backgroundColor = .red
v.text = "Testing"
return v
}()
let regionsPicker: UIPickerView = {
let v = UIPickerView()
v.backgroundColor = .green
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .cyan
// add the label
view.addSubview(regionsLabel)
// center label horizontally, 10-pts from view top (safe area)
regionsLabel.snp.makeConstraints { (make) in
make.centerX.equalToSuperview()
make.top.equalTo(self.view.safeAreaLayoutGuide.snp.top).offset(10)
}
// add the picker view
view.addSubview(regionsPicker)
// rotate the picker view
let rotationAngle: CGFloat = -90 * (.pi/180)
regionsPicker.transform = CGAffineTransform(rotationAngle: rotationAngle)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
regionsPicker.snp.remakeConstraints { (make) in
// constrain picker view center horizontally
make.centerX.equalToSuperview()
// constant of 100 - because it's rotated, set the width
make.width.equalTo(100)
// constrain the height to a constant equal to the view width
make.height.equalTo(view.bounds.width)
// constrain the centerY to the centerY of the label,
// plus one-half the label's frame height / 2
// plus a constant of 65 (half the "height" of the picker view + 15-pts spacing)
make.centerY.equalTo(regionsLabel.snp.centerY).offset(regionsLabel.frame.height / 2.0 + 65.0)
}
}
}
这导致:
我用SnapKit比较习惯,但是不知道怎么解决这个问题
这是我现在的 UI 的样子:
为了实现这一目标,我这样做:
override func viewDidLoad() {
super.viewDidLoad()
regionsPicker.snp.makeConstraints { (make) in
make.centerX.equalToSuperview()
make.height.equalToSuperview() // since we rotate (this is the width)
make.top.equalTo(regionsLabel.snp.bottom).offset(15)
make.width.equalTo(100)
}
rotationAngle = -90 * (.pi/180)
regionsPicker.transform = CGAffineTransform(rotationAngle: rotationAngle)
}
如上所示,我正在尝试将标签的底部与选择器视图的顶部对齐。但是由于我正在旋转我的视图,使高度等于超级视图,所以它创建了这个巨大的 space。
我看到
感谢您的帮助。
问题出在Apple文档中transform的这部分描述:https://developer.apple.com/documentation/uikit/uiview/1622459-transform
In iOS 8.0 and later, the transform property does not affect Auto Layout. Auto layout calculates a view’s alignment rectangle based on its untransformed frame. So, when you change the text of the label, your constraints are related to the untransformed frame.
因此,您将 pickerView 的 height 设置为视图的 height。然后旋转它,它会 出现 以显示您想要的外观。
不过,如果您使用 Debug View Hierarchy
,您会看到 pickerView 现在延伸到其 superView 的前缘和后缘之外。
您还会看到 pickerView 的 bounds 的宽度和高度 - 100 x 667
(在 iPhone 8) - 这不是你所期望的。
当视图大小发生变化时(例如在设备旋转时),这也会出现问题。
这是一个示例方法:
import UIKit
class ViewController: UIViewController {
let regionsLabel: UILabel = {
let v = UILabel()
v.backgroundColor = .red
v.text = "Testing"
return v
}()
let regionsPicker: UIPickerView = {
let v = UIPickerView()
v.backgroundColor = .green
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .cyan
// add the label
view.addSubview(regionsLabel)
// center label horizontally, 10-pts from view top (safe area)
regionsLabel.snp.makeConstraints { (make) in
make.centerX.equalToSuperview()
make.top.equalTo(self.view.safeAreaLayoutGuide.snp.top).offset(10)
}
// add the picker view
view.addSubview(regionsPicker)
// rotate the picker view
let rotationAngle: CGFloat = -90 * (.pi/180)
regionsPicker.transform = CGAffineTransform(rotationAngle: rotationAngle)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
regionsPicker.snp.remakeConstraints { (make) in
// constrain picker view center horizontally
make.centerX.equalToSuperview()
// constant of 100 - because it's rotated, set the width
make.width.equalTo(100)
// constrain the height to a constant equal to the view width
make.height.equalTo(view.bounds.width)
// constrain the centerY to the centerY of the label,
// plus one-half the label's frame height / 2
// plus a constant of 65 (half the "height" of the picker view + 15-pts spacing)
make.centerY.equalTo(regionsLabel.snp.centerY).offset(regionsLabel.frame.height / 2.0 + 65.0)
}
}
}
这导致: