以编程方式在子类 UIView 的子视图上自动布局
Posted
技术标签:
【中文标题】以编程方式在子类 UIView 的子视图上自动布局【英文标题】:Autolayout programmatically on a subview of a subclassed UIView 【发布时间】:2012-11-20 16:54:39 【问题描述】:我对 UIView 进行了子类化,以创建一个自定义 groupView,我可以使用它以一种简单的方式将一些东西添加到我的布局中。这个 groupView 包括一个用作标题的 UILabel 和一个在它的 CALayer 上绘制一个带有背景颜色的 roundRect 的 UIView。想想 UITableView 的部分。我通过删除 UIView 并将其类更改为我的子类来将此 groupView 添加到情节提要。一切正常,我通过 Xcode 中用户定义的运行时属性设置标题。一切都很好,我在情节提要的这个视图中添加了 UILabels,它在运行时创建了标题标签和圆形矩形。
我的 groupView 的结构:
-
groupView: (UIView)clipToBounds:NO;
标题:(UILabel)定位
在 groupView 上方。
contentView:(UIView) 创建roundRect
通过 CALayer 和颜色,应该与 groupView 的大小相同。
那么问题是什么?好吧,开始处理自动布局是一件很痛苦的事情,但是要让这个子类 UIView 工作,我需要以编程方式设置 contentView 约束。我无法弄清楚这个自动布局 ASCII 格式字符串的语法。目前我有:
_contentView = [[UIView alloc]initWithFrame:self.bounds];
_contentView.layer.cornerRadius = 5.0f;
_contentView.layer.masksToBounds=YES;
_contentView.backgroundColor=_backgroundColor;
_contentView.layer.borderWidth=_borderWidth;
_contentView.layer.borderColor=_borderColor.CGColor;
[self insertSubview:_contentView atIndex:0];
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(self,_contentView);
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"[self]-0-[_contentView]-0-[self]" options:0 metrics:nil views:viewsDictionary];
for (NSLayoutConstraint *constraint in constraints)
[_contentView addConstraint:constraint];
哪个崩溃:* 由于未捕获的异常“NSGenericException”而终止应用程序,原因:“无法在视图上安装约束。约束是否引用了视图子树之外的内容?那是违法的。约束:视图:>'
我先试过了,还是不行:
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_contentView);
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-0-[_contentView]-0-|" options:0 metrics:nil views:viewsDictionary];
哪个崩溃:* 由于未捕获的异常“NSGenericException”而终止应用程序,原因:“无法在视图上安装约束。约束是否引用了视图子树之外的内容?那是违法的。约束:视图:>'
咆哮:不知何故,这个 AutoLayout 应该可以节省我们的工作,但是 我现在看不出好处是如何超过开销的。为什么 他们到底是不是从使用引用和方法甚至是类型 defs 到这个古老的格式字符串?这样做会容易得多: [_contentView 约束:NSLayoutFormatAlignLeading toView:self withDistance:0.0f];或者类似的东西?我宁愿交易 此时带有弹簧和支柱。
任何帮助理解或向我展示将 contentView 限制为 self 大小的语法都会有所帮助。
【问题讨论】:
关于您的咆哮:自动布局有一个学习曲线,一开始您确实倾向于讨厌它 - 但是一旦您完全考虑约束而不是框架,它就会变得更容易。而且“视觉格式”是毫无用处的,除非你只是把东西排成一排。另一种方法(constraintWithItem...)基本上是您在上面的咆哮中所使用的语法。 如果其他人在理解这个 ASCII-Art 格式字符串时遇到问题,我发现本教程很有帮助。我知道它适用于 Ruby,但格式字符串与 Objective-C 中的相同。 seanlilmateus.github.com 【参考方案1】:错误告诉你你需要知道什么:
约束是否引用了视图子树之外的东西?
是的。它引用了它的超级视图。
您需要将这些约束应用于超级视图,在本例中为groupView
。
【讨论】:
好的,但这不是子视图的约束吗?这是我需要自动调整大小的子视图。我只是想错了吗? 这样想:它限制了contentView
在groupView
中的位置和大小。请参阅安装约束部分:developer.apple.com/library/mac/#documentation/UserExperience/…
好的,是的,我现在明白了,这就是为什么 Xcode 中的约束显示在 superViews 下而不是视图本身。仍然有语法问题。回到文档,也许它会在这个时候沉没。感谢您的洞察力。【参考方案2】:
该 |字符代表视觉格式语言中的超级视图,所以我想你想要:
@"|-0-[_contentView]-0-|"
然后您需要将约束添加到 self 而不是 contentView,因为您需要将其添加到可以看到所有参与者的视图中。
以下是视觉语言的参考: https://developer.apple.com/library/mac/#documentation/UserExperience/Conceptual/AutolayoutPG/Articles/formatLanguage.html#//apple_ref/doc/uid/TP40010853-CH3-SW1
您也可以完全避免使用视觉格式:
+(id)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c
【讨论】:
如果你将约束添加到self而不是contentView,那么管道(|)会引用self的superview吗?【参考方案3】:尝试检查约束,它们是否正确添加到视图中
例如:
UIView *yellowView = [[UIView alloc] init];
yellowView.backgroundColor = [UIColor yellowColor];
yellowView.translatesAutoresizingMaskIntoConstraints = false;
[self.view addSubview:yellowView];
//ios 9 last
NSLayoutConstraint *heightAnchor = [yellowView.heightAnchor constraintEqualToAnchor:self.purView.heightAnchor];
// addConstraints
[self.view addConstraints:@[heightAnchor]];
[self.view setNeedsLayout];
如果添加heightAnchor to
yellowView
喜欢关注。它会显示错误
[yellowView addConstraints:@[heightAnchor]];
【讨论】:
以上是关于以编程方式在子类 UIView 的子视图上自动布局的主要内容,如果未能解决你的问题,请参考以下文章
UICollectionViewCell 以编程方式自动布局