如何在转换中使用AutoLayout

时间:2018-11-02 02:02:10

标签: ios autolayout

苹果文件说:

  

在iOS 8.0和更高版本中,transform属性不会影响“自动布局”。自动布局会根据视图的未变形帧来计算视图的对齐矩形。

因此,如果我有一个名为 View1 的视图,该视图通过使用transform属性和 View2 < / em> 要与 View1 的边缘对齐。我该如何使用 AutoLayout

1 个答案:

答案 0 :(得分:3)

好问题。正如您所引用的,约束条件适用于视图的原始未变换范围。

为了能够使您的其他视图尊重变换后的边界,一种方法是在应用变换后计算约束常数的偏移量。下面是一个与您的情况类似的示例,但有一个最大的约束,而不是 leading / trailing / align 。但基本上,您也可以对其他情况应用相同的过程。

这暂时有效,请随时改进此答案。


故事板设置:

Storyboard Setup

应用(scaleX:3, scaleY:2.5)变换后的输出。


我们在下面的代码中所做的是:

  1. 使约束IBOutlet
  2. 将约束的原始常量存储到变量中。
  3. 在应用之前,先存储要缩放的视域。
  4. 应用变换。
  5. 在转换后存储视图框架。

注意::根据Apple文档,它说:

  

警告
  当此属性的值不是   身份转换,未定义frame属性中的值,并且   应该被忽略。

但是在应用比例尺后,转换后的框架似乎可以使用。因此,我们将其保存到变量中以备将来使用。如果尝试访问其他位置的框架,则不会获得正确的框架。因此,我们在应用转换后立即执行此步骤。

  1. 通过重写ViewController的updateViewConstraints方法,您将有机会更新约束。现在,我们简单地将两个帧的底部位置的差值应用于IBOutlet的约束常数。

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var view1: UIView! //Dark gray view
    @IBOutlet weak var view2: UIView! //Light gray view

    @IBOutlet weak var topConstraint: NSLayoutConstraint!

    let transformScaleX:CGFloat = 3
    let transformScaleY:CGFloat = 2.5

    var rectBeforeTransform:CGRect = .zero
    var rectAfterTransform:CGRect = .zero

    var originalTopConstraintConstant:CGFloat = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        //Store original constraint value
        self.originalTopConstraintConstant = self.topConstraint.constant
        //Store unaltered frame of the view
        self.rectBeforeTransform = view1.frame
        //Apply transform
        self.view1.transform = .init(scaleX: transformScaleX, y: transformScaleY)
        //Frame after transform.
        //NOTE: When a non-identity transform is applied to a view, its frame is undefined, so we would not get proper frame info. of the view anywhere other than after applying the tranform.
        self.rectAfterTransform = view1.frame
    }

    override func updateViewConstraints() {
        DispatchQueue.main.async {
            let constraintOffset = abs(self.rectAfterTransform.bottomY - self.rectBeforeTransform.bottomY)
            self.topConstraint.constant = self.originalTopConstraintConstant + constraintOffset
        }
        super.updateViewConstraints()
    }

}

extension CGRect {
    var bottomY:CGFloat {
        get {
            return self.height + self.origin.y
        }
    }
}

PS:当前答案仅适用于最高限制条件,我将尝试针对所有 leading / trailing / top / bottom 限制条件(可能是更优雅的解决方案。至于动画,很遗憾,我无法提供解决方法。如果发现一些会更新。谢谢。