CATransform3DMakeRotation frame

时间:2018-04-22 09:14:12

标签: ios swift core-animation

我有一个自定义视图MyView(红色),其中包含一个子视图MySubView(蓝色)。我想围绕其中心旋转子视图。

我的问题是,当我使用autolayout设置MySubview时,旋转正常:

enter image description here enter image description here

但是当我设置子视图的框架(没有自动布局)时,旋转会扭曲视图:

enter image description here

MySubview类中,我公开了一个设置旋转的属性,如下所示

var rotateAngle: Int = 0 {
    didSet {
        let measurement = Measurement(value: Double(rotateAngle), unit: UnitAngle.degrees)
        let radians = measurement.converted(to: UnitAngle.radians).value
        layer.transform = CATransform3DMakeRotation(CGFloat(radians), 0.0, 0.0, 1.0)
    }
}

MyView中,使用

设置自动布局
subview.translatesAutoresizingMaskIntoConstraints = false

NSLayoutConstraint.activate([
    subview.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.5),
    subview.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 0.5),
    subview.centerXAnchor.constraint(equalTo: centerXAnchor),
    subview.centerYAnchor.constraint(equalTo: centerYAnchor),

    ])

当我在不使用自动布局的情况下进行设置时,我只需设置子视图框

override func layoutSubviews() {
    super.layoutSubviews()
    subview.frame = CGRect(origin: CGPoint(x: frame.width / 4, y: frame.height / 4), size: CGSize(width: frame.width / 2, height: frame.height / 2))
}

我不想使用autolayout的原因是因为在真实的应用程序中,我经常刷新数百个视图,在没有自动布局的情况下表现更好。

以下是

的完整列表
class RotateViewController: UIViewController {

    @IBOutlet var myView: MyView!
    @IBOutlet var slider: UISlider!

    override func viewDidLoad() {
        myView = MyView()
        view.addSubview(myView)

        myView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            myView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            myView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            myView.widthAnchor.constraint(equalToConstant: 60),
            myView.heightAnchor.constraint(equalToConstant: 60)
            ])

    }

    @IBAction func sliderValueChanged() {
        myView.subview.rotateAngle = Int(slider.value)
    }
}

class MySubView: UIView {

    var rotateAngle: Int = 0 {
        didSet {
            let measurement = Measurement(value: Double(rotateAngle), unit: UnitAngle.degrees)
            let radians = measurement.converted(to: UnitAngle.radians).value
            layer.transform = CATransform3DMakeRotation(CGFloat(radians), 0.0, 0.0, 1.0)
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .blue

    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        backgroundColor = .blue;
    }
}

class MyView: UIView {

    let useAutoLayout = false

    var subview = MySubView()

    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubview(subview)
        backgroundColor = .red
        setupConsraints()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        addSubview(subview)
        backgroundColor = .red
        setupConsraints()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        if useAutoLayout {
            return
        }
        subview.frame = CGRect(origin: CGPoint(x: frame.width / 4, y: frame.height / 4), size: CGSize(width: frame.width / 2, height: frame.height / 2))
    }

    private func setupConsraints() {
        if !useAutoLayout {
            return
        }
        subview.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            subview.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.5),
            subview.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 0.5),
            subview.centerXAnchor.constraint(equalTo: centerXAnchor),
            subview.centerYAnchor.constraint(equalTo: centerYAnchor),

            ])
    }
}

3 个答案:

答案 0 :(得分:0)

这是因为重新运行了这个

override func layoutSubviews() {
    super.layoutSubviews()

    if(once)
    {
        subview.frame = CGRect(origin: CGPoint(x: frame.width / 4, y: frame.height / 4), size: CGSize(width: frame.width / 2, height: frame.height / 2))

        print(subview.frame)

        once = false
    }
}

答案 1 :(得分:0)

阅读docs of UIView之后,我认为根本原因是在将transform属性设置为其他标识后,框架变为无效:

  

如果transform属性不是identity变换,则此属性的值是未定义的,因此应该被忽略。

因此,我可以使用其边界来设置它,而不是使用旋转视图的frame

override func layoutSubviews() {
    super.layoutSubviews()
    subview.bounds.size = CGSize(width: frame.width / 2, height: frame.height / 2)
    subview.center = CGPoint(x: frame.width / 2, y: frame.height / 2)
}

答案 2 :(得分:0)

问题在于您不断重置视图的帧,这会导致transform失效。在MyView更新setupConsraints()

private func setupConsraints() {
    if !useAutoLayout {
        subview.frame = CGRect(origin: CGPoint(x: frame.width / 4, y: frame.height / 4), size: CGSize(width: frame.width / 2, height: frame.height / 2))
        return
    }
    subview.translatesAutoresizingMaskIntoConstraints = false

    NSLayoutConstraint.activate([
        ...
        ])
}

然后您可以完全删除layoutSubviews()功能。