我在UIImageView
中嵌入了UIView
。我的整个应用都使用AutoLayout
,但我想删除constraints
的{{1}}。 UIImageView
不允许我删除Xcode
,有没有办法为特定对象禁用它们,将它们设置为零,是什么?
答案 0 :(得分:88)
我同意如果你想要一些特别的东西,Xcode自动布局是非常糟糕的......
我用什么来以编程方式删除约束:
[detailsPhotoView removeConstraints:detailsPhotoView.constraints];
答案 1 :(得分:25)
在XCode 5中,编辑约束时有一个选项'在构建时删除'。如果启用此选项,则会在运行时自动删除约束。如果您不需要特定约束,可以选择使Interface Builder保持高兴。
答案 2 :(得分:8)
这里有两个不同的问题:
关于(1),jturton是正确的。只要您在Xcode中启用了自动布局,Xcode就会保证/要求有足够的约束来唯一地确定视图的大小和位置。
如果你没有在Xcode中手动指定足够的约束(通过布局检查器中以蓝色显示的“用户约束”),那么Xcode将添加它猜测的新约束(以紫色显示),直到有足够的约束确定布局。
如果UIImageView没有约束,它的布局将无法确定,因此您无法在Xcode中进行设置。要解决这个问题,你应该做的是使用Xcode将IBOutlets设置为你要删除的所有约束,然后在你的UIView的awakeFromNib:或你的UIViewController的viewDidLoad中:你通过调用removeConstraints手动删除约束:。
但是,现在你的UIImageView的布局是不确定的。所以此时你需要手动添加新的约束,这些约束将允许你移动和调整UIImageView的大小,这让我们回答问题(2)。
关于(2),如何调整大小&移动一个视图,其布局由约束决定,答案是像往常一样设置手势识别器来检测捏合和放大。 pan手势,但不是那些调用setFrame的手势识别器:修改视图,他们应该修改确定UIImageView框架的NSLayoutConstraint的constant
参数,然后调用layoutIfNeeded:,这将导致布局系统立即将修改后的约束转换为新框架。
因此,例如,假设您想要使用一组与熟悉的setFrame:调用非常相似的布局约束来操作UIImageView。在这种情况下,在通过Xcode删除约束设置之后,您可以向视图添加约束,从约束的顶部和左侧指定其宽度,高度和空间。然后你的平移手势识别器的动作处理程序,只会更新起搏手势识别器的常量参数,你的捏手势识别器可以只更新高度和宽度约束的常量参数。
另一种做(2)的方法是设置translatesAutoresizingMaskIntoConstraints=YES
,它在引擎盖下相同但在实践中可能更容易。这将做两件事。它将使自动布局系统根据视图的autoresizingMask在视图的超级视图中自动生成约束。第二 - 至关重要! - 它将使布局系统自动将对setFrame的调用转换为对这些约束的修改。
答案 3 :(得分:6)
你不能没有约束 - 你必须有足够的约束来明确地确定每个视图的大小和位置
您可以创建使用Autolayout布局的可调整大小的视图。
例如,在您的情况下,您可以创建定位约束 - 例如,将图像视图的中心水平和垂直地固定在其超视图的中心。
您还可以水平和垂直创建大小约束。有关如何执行此操作,请参阅我的回答here。为这两个约束创建出口(如果使用接口构建器)。您可以具有特定数字的高度和宽度约束,或使用乘数来设置固定的宽高比。
为了响应捏合手势,您可以调整两个大小限制的.constant
属性,然后调用setNeedsLayout
。这将调整图像视图的大小,同时保持其中心固定。
如果您执行上述固定宽高比建议,则使用约束调整视图大小实际上比设置框架简单得多。
答案 4 :(得分:5)
你可以打电话
[yourElement removeFromSuperview];
然后致电
[yourSuperview addSubview:yourElement];
从yourElement
中移除所有约束并将其添加回视图。
值得一提的是,如果您在UIView类别或扩展程序上执行上述操作,则需要在从superview中删除之前保存对视图的superview的引用:
var theSuperview = self.superview
self.removeFromSuperview()
theSuperview?.addSubview(self)
你可能还需要使你的元素变强而不是弱,因为从superview中删除可能会导致你失去对它的引用。
答案 5 :(得分:4)
如果您只是想从层次结构中删除视图,只需调用[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;
}
该方法将已删除的约束传递回您可以保留在某个位置的数组,以便稍后可以添加约束。
使用它有点像这样......
NSArray *const removedConstraints = [viewToHide stealExternalConstraintsUpToView: self.view];
[viewToHide setHidden: YES];
稍后,将约束放回去。
从iOS 8开始,您无需考虑应该在何处放置约束。只需使用此...
[NSLayoutConstraint activateConstraints: removedConstraints];
[viewToHide setHidden: NO];
使用早期版本的iOS,您无需仔细考虑将约束添加回去的位置。然后扔进控制器的self.view
。如果约束在他们影响的所有视图的 a 超级视图中,它们将起作用。
[self.view addConstraints: removedConstraints];
[viewToHide setHidden: NO];