我有一个UIImageView
嵌入在UIView
. 我的整个应用程序都使用,AutoLayout
但我想删除constraints
. 不允许我删除,有没有办法为特定对象禁用它们,将它们设置为零,什么?UIImageView
Xcode
constraints
6 回答
我同意如果你想要一些特别的东西,Xcode 自动布局会很糟糕......
我用来以编程方式删除约束的方法:
[detailsPhotoView removeConstraints:detailsPhotoView.constraints];
在 XCode 5 中,编辑约束时有一个选项“在构建时删除”。如果启用此功能,则在运行时将自动删除约束。如果您不想要特定的约束,该选项可以让 Interface Builder 满意。
这里有两个不同的问题:
- 如何使用 Xcode 设置没有约束的 UIImageView
- 当 UIImageView 的布局由约束处理时,如何允许平移和/或调整其大小。
关于(1),jturton 是正确的。只要您在 Xcode 中启用了自动布局,Xcode 就会保证/要求有足够的约束来唯一地确定视图的大小和位置。
如果您没有在 Xcode 中手动指定足够的约束(通过布局检查器中以蓝色显示的“用户约束”),那么 Xcode 将添加它猜测的新约束(以紫色显示),直到有足够的约束来确定布局。
如果 UIImageView 没有约束,它的布局将无法确定,所以你不能在 Xcode 中设置它。要解决此问题,您应该使用 Xcode 将 IBOutlets 设置为要删除的所有约束,然后在 UIView 的 awakeFromNib: 或 UIViewController 的 viewDidLoad: 中通过调用 removeConstraints: 手动删除约束。
但是,现在您的 UIImageView 的布局尚未确定。因此,此时您将需要手动添加新的约束,以允许您移动和调整 UIImageView 的大小,这将我们带入问题 (2)。
关于(2),如何调整和移动布局由约束决定的视图,答案是像往常一样设置手势识别器来检测捏和平移手势,而不是那些调用 setFrame: 的手势识别器来修改视图,他们应该修改constant
确定 UIImageView 框架的 NSLayoutConstraint 的参数,然后调用 layoutIfNeeded:,这将导致布局系统立即将修改后的约束转换为新框架。
因此,例如,假设您想使用一组布局约束来操作 UIImageView,这些约束与熟悉的 setFrame: 调用非常相似。在这种情况下,在移除 Xcode 设置的约束后,您可以向视图添加约束,指定其宽度、高度以及父视图顶部和左侧的空间。然后,您的平移手势识别器的动作处理程序将只更新起搏器手势识别器的常量参数,而您的捏合手势识别器可以只更新高度和宽度约束的常量参数。
做 (2) 的另一种方法是设置translatesAutoresizingMaskIntoConstraints=YES
. 这将做两件事。它将导致自动布局系统根据视图的 autoresizingMask 在视图的父视图中自动生成约束。第二——至关重要!– 它将导致布局系统自动将对 setFrame: 的调用转换为对这些约束的修改。
你不能没有约束——你必须有足够的约束来明确地调整每个视图的大小和位置
您可以创建使用 Autolayout 布局的可调整大小的视图。
例如,在您的情况下,您可以创建定位约束 - 例如,将图像视图的中心水平和垂直固定在其父视图的中心。
您还可以在水平和垂直方向上创建尺寸限制。请在此处查看我的答案,了解如何执行此操作。为这两个约束创建出口(如果使用界面生成器)。您可以有特定数字的高度和宽度约束,或者使用乘数来制作固定的纵横比。
针对捏合手势,可以调整.constant
两个大小约束的属性,调用setNeedsLayout
. 这将调整您的图像视图的大小,同时保持其中心固定。
如果您执行上述固定纵横比建议,则使用约束调整视图大小实际上比设置框架要简单得多。
你可以打电话
[yourElement removeFromSuperview];
然后打电话
[yourSuperview addSubview:yourElement];
删除所有约束yourElement
并将其添加回视图。
值得一提的是,如果您在 UIView 类别或扩展等上执行上述操作,则需要在从超级视图中删除之前保存对视图超级视图的引用:
var theSuperview = self.superview
self.removeFromSuperview()
theSuperview?.addSubview(self)
您可能还需要使 yourElement 强而不是弱,因为从超级视图中删除可能会导致您丢失对它的引用。
如果您只是想从层次结构中删除视图,只需调用[theView removeFromSuperview]
. 任何影响它的约束也将被删除。
但是,有时您可能还想放回视图,暂时将其删除。
为了实现这一点,我在UIView
. 它将视图层次结构从一个视图向上v
移动到某个最终容器视图c
(通常是您的视图控制器的根视图),并删除v
. 这些是与 的兄弟姐妹的约束v
,而不是仅影响v
的孩子的约束。你可以隐藏v
。
-(NSArray*) stealExternalConstraintsUpToView: (UIView*) superview
{
NSMutableArray *const constraints = [NSMutableArray new];
UIView *searchView = self;
while(searchView.superview && searchView!= superview)
{
searchView = searchView.superview;
NSArray *const affectingConstraints =
[searchView.constraints filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:^BOOL(NSLayoutConstraint *constraint, NSDictionary *bindings)
{
return constraint.firstItem == self || constraint.secondItem == self;
}]];
[searchView removeConstraints: affectingConstraints];
[constraints addObjectsFromArray: affectingConstraints];
}
return constraints;
}
该方法将删除的约束传回一个数组中,您可以将其保留在某个地方,以便稍后您可以添加回约束。
使用它有点像这样......</p>
NSArray *const removedConstraints = [viewToHide stealExternalConstraintsUpToView: self.view];
[viewToHide setHidden: YES];
稍后,将约束放回去。
从 iOS 8 开始,您无需考虑应该将约束放在哪里。就用这个……</p>
[NSLayoutConstraint activateConstraints: removedConstraints];
[viewToHide setHidden: NO];
使用早期版本的 iOS,您无需考虑在哪里添加约束。然后扔进控制器的self.view
. 如果约束在它们影响的所有视图的超级视图中,它们就会起作用。
[self.view addConstraints: removedConstraints];
[viewToHide setHidden: NO];