为什么不设置UIView的边界将其大小限制为那些边界

时间:2016-02-26 16:35:21

标签: swift

我想关闭自动布局一段时间,并使用boundscentertransformation来处理UIView的大小和位置。

我有一个非常简单的“单视图应用程序”示例。我的应用程序有一个托管主视图的视图控制器。在该视图中有两个按钮和另一个视图(背景设置为粉红色),后者又包含一个图像视图(设置为宽高比):

Xcode screenshot showing storyboard

我已经将我的问题提炼成一个非常简单的UIViewController:

@IBOutlet weak var imageHolderView: UIView!
@IBOutlet weak var imageView: UIImageView!

@IBAction func loadImageButtonClicked(sender: AnyObject) {
    let url = NSURL(string: "https://c2.staticflickr.com/4/3909/15110089915_21a12eba6a_k.jpg")
    let data = NSData(contentsOfURL: url!)
    self.imageView.image = UIImage(data: data!)
}

@IBAction func clearConstraintsButtonClicked(sender: AnyObject) {
    let bounds:CGRect = self.imageHolderView.bounds
    let center:CGPoint = self.imageHolderView.center
    NSLayoutConstraint.deactivateConstraints(self.imageHolderView.constraints)
    self.imageHolderView.bounds = bounds
    self.imageHolderView.center = center
}

N.B。我试图在一个更复杂的项目中理解这一点,这里的例子只是为了证明这个问题。

当我运行项目时,图像没有来源,所以粉红色的UIView(imageHolderView)占据了预期的大部分屏幕:

simulator screenshot before image loaded

当我单击加载图像按钮时,控制器将图像从Web加载到UIImageView中。因为约束仍然存在,所以自动布局确保图片在UIImageView中被方面拟合约束到其超级视图imageHolderView

simulator screenshot after image loaded

如果我现在清除约束,我希望看到没有区别,因为自动布局设置的约束会立即在代码中被相同的值替换。但那不是我所看到的:

simulator screenshot after constraints are cleared

如何抓取自动布局设置的UIView的边界和中心,关闭UIView的自动布局,然后从我自己的swift代码重新建立边界和居中?

在调试器中查看UIView imageHolderView上的边界是正确的,并且UIImageView imageView上的约束几乎(*)仍然存在(我希望将UIImageView限制为适合UIView),但UIImageView上的界限已经增长,以适应全尺寸图像。为什么呢?

(在更复杂的应用程序中,我继续调整大小,旋转和转换视图。Apple's documentation声明“如果transform属性包含非标识变换,则为frame属性的值未定义且不应修改。在这种情况下,您可以使用center属性重新定位视图,并使用bounds属性调整大小。“示例代码不使用转换,但正如我所说的我的真实代码所做的;我认为这使我无法设置框架。)

(*)我差点说,因为UIImageView有四个约束,但在调试器中,计数是两个。

4 个答案:

答案 0 :(得分:3)

有几件事你忘记了。

首先,在:

NSLayoutConstraint.deactivateConstraints(self.imageHolderView.constraints)

确保您没有停用所需的约束。例如。如果您在imageHolderView上有宽度或高度限制,则可以使用此调用停用它。

在:

let bounds:CGRect = self.imageHolderView.bounds
let center:CGPoint = self.imageHolderView.center
NSLayoutConstraint.deactivateConstraints(self.imageHolderView.constraints)
self.imageHolderView.bounds = bounds
self.imageHolderView.center = center

您正在获取bounds的{​​{1}}和center,然后您尝试将它们分配回imageHolderView。这是错误的,因为您正在停用设置imageHolderView位置的约束。您不必更改imageView的位置,因为它的约束会保存在其超级视图中。另一方面,self.imageHolderView可能已禁用所有约束,因此您应该设置其位置:

self.imageView

self.imageView.bounds = bounds self.imageView.center = center 设置错误,因为在其超级视图的坐标系中指定了center。您应该从imageHolderView.center手动计算中心。

bounds

然而,最大的问题可能是这样的事实:默认情况下,在启用了autolayout的storyboard / xib中创建的任何视图中,self.imageView.center = CGPointMake(bounds.size.width / 2, bounds.size.height / 2) bounds(或center)都会被忽略

您必须手动将frame设置为imageView.translatesAutoresizingMaskIntoConstraints。否则布局管理器将忽略true

答案 1 :(得分:2)

不要设置边界,而是设置框架。试试这个:

@IBAction func clearConstraintsButtonClicked(sender: AnyObject) {
    let frame = self.imageHolderView.frame
    NSLayoutConstraint.deactivateConstraints(self.imageHolderView.constraints)
    self.imageHolderView. frame = frame
}

答案 2 :(得分:2)

由于您正在清除视图的包含内容,因此它将删除其子视图的垂直和水平拥抱约束。你可以通过自定义你的持有人来解决这个问题,

class CustomHolderView: UIView {
    @IBOutlet weak var imageView: UIImageView!

    override func layoutSubviews() {
        super.layoutSubviews() 
        self.imageView.frame = self.bounds
    }
}

在holder holder视图layoutSubviews方法中,您应该为图像视图设置框架。

答案 3 :(得分:1)

UIImageView会根据其大小调整掩码及其contentMode自动添加约束。尝试将其contentMode设置为AspectFitAspectFill并操纵其frame而不是bounds