Macos OSX Cocoa自动布局隐藏元素
我正在尝试使用新的Lion,因为它看起来很不错。但我找不到关于如何做事的好信息。例如: 我有两个标签:Macos OSX Cocoa自动布局隐藏元素,macos,cocoa,osx-lion,Macos,Cocoa,Osx Lion,我正在尝试使用新的Lion,因为它看起来很不错。但我找不到关于如何做事的好信息。例如: 我有两个标签: +----------------+ | +------------+ | | + label 1 | | | +------------+ | | | | +------------+ | | | label 2 | | | +------------+ | +----------------+ 但是,第一个标签并不总是填充内容,有时根本没有内容。
+----------------+
| +------------+ |
| + label 1 | |
| +------------+ |
| |
| +------------+ |
| | label 2 | |
| +------------+ |
+----------------+
但是,第一个标签并不总是填充内容,有时根本没有内容。我想做的是自动显示标签2,当标签1包含内容时,标签1将位于何处
+----------------+
| +------------+ |
| + label 2 | |
| +------------+ |
| |
| |
| |
| |
+----------------+
我必须添加哪些约束才能自动与autolayout配合使用?我知道我可以编写所有的代码,但我有大约30个这样的标签、图片和按钮,它们的样式和形状都是可选的,我不想在自动运行时添加数百行代码
如果它不起作用,那么我将只使用WebView,并使用HTML和CSS进行操作。我不认为您可以这样做。如果使标签2的布局基于标签1的距离约束,即使在没有内容时使标签1自动折叠为零高度,标签2仍将向下移动该距离,即:
+----------------+
| +------------+ |
| + label 1 | |
| +------------+ |
| ^ |
| ^ !
| +------------+ |
| | label 2 | |
| +------------+ |
+----------------+
其中^是自动布局距离约束-如果标签1知道如何在其字符串为空时变为零高度,则仍然会得到:
+----------------+
| +------------+ |
| ^ |
| ^ !
| +------------+ |
| | label 2 | |
| +------------+ |
+----------------+
也许可以手动创建NSLayoutConstraint。您可以将第二个属性设置为标签1的高度,将常数设置为零,然后根据非零标签高度的倍数仔细计算出使距离成为所需距离的乘数
但在完成所有这些之后,您现在编写了一个NSLabel子类,该子类可以自动调整大小,手动而不是通过可视化语言创建约束对象,并使NSLayoutConstraint超出其意愿
我认为如果标签1的字符串为空,您最好只更改标签2的框架 这在自动布局中是可能的,但不能很好地进行缩放 所以,以您的示例为例,假设您有标签A和标签B(或者按钮或其他任何东西)。首先为a向superview添加顶部约束,然后在a和B之间添加垂直间距约束。到目前为止,这都是正常的。如果此时要删除A,B的布局将不明确。如果要隐藏它,它仍然会占用它的空间,包括标签之间的空间 接下来,需要将另一个约束从B添加到superview的顶部。将此项的优先级更改为低于其他项(例如900),然后将其常量设置为标准值(或其他较小的值)。现在,当A从其superview中移除时,较低优先级约束将生效并将B拉向顶部。约束如下所示:
当你试图用一长串标签来做这件事时,问题就来了。我也找到了一个看起来不错的方法来做这件事。类似于。下面是它在代码中的工作方式。我创建了superview及其所有子视图,甚至那些可能并不总是显示的子视图。我向superview添加了许多约束,例如
V:|-[\u btn]
。正如您在这些约束的末尾所看到的,superview上没有指向底部的链接。然后,我为视图的两种状态创建了两个约束数组,对我来说,不同之处是“更多选项”三角形。然后,根据三角形的状态单击该三角形时,我会相应地添加和删除约束和子视图。例如,要添加我所做的:
[self.backgroundView removeConstraints:self.lessOptionsConstraints];
[self.backgroundView addSubview:self.nameField];
[self.backgroundView addConstraints:self.moreOptionsConstraints];
我删除的约束将按钮绑定到superview的底部,如
V:[\u btn]-|
。我添加的约束看起来像V:[\u btn]-[\u nameField]-|
,因为您可以看到此约束将新视图放置在其上方的原始视图和扩展superview高度的superview底部之间。以下是我如何通过编程而不是使用Interface Builder处理此问题的示例。总之,;我仅在启用视图的情况下添加该视图,然后在子视图上迭代,并在执行时添加垂直约束
请注意,相关视图在此之前已初始化
/*
Begin Auto Layout
*/
NSMutableArray *constraints = [NSMutableArray array];
NSMutableDictionary *views = [[NSMutableDictionary alloc] init];
/*
Label One
*/
if (enableLabelOne) {
[contentView addSubview:self.labelOne];
self.labelOne.translatesAutoresizingMaskIntoConstraints = NO;
[views setObject:self.labelOne
forKey:@"_labelOne"];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_labelOne(44)]"
options:0
metrics:nil
views:views]];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_labelOne]-|"
options:0
metrics:nil
views:views]];
}
/*
Label Two
*/
if (enableLabelTwo) {
[contentView addSubview:self.labelTwo];
self.labelTwo.translatesAutoresizingMaskIntoConstraints = NO;
[views setObject:self.labelTwo
forKey:@"_labelTwo"];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_labelTwo(44)]"
options:0
metrics:nil
views:views]];
}
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_labelTwo]-|"
options:0
metrics:nil
views:views]];
/*
Dynamically add vertical spacing constraints to subviews
*/
NSArray *subviews = [contentView subviews];
if ([subviews count] > 0) {
UIView *firstView = [subviews objectAtIndex:0];
UIView *secondView = nil;
UIView *lastView = [subviews lastObject];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[firstView]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(firstView)]];
for (int i = 1; i < [subviews count]; i++) {
secondView = [subviews objectAtIndex:i];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[firstView]-10-[secondView]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(firstView, secondView)]];
firstView = secondView;
}
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[lastView]-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(lastView)]];
}
[self addConstraints:constraints];
/*
开始自动布局
*/
NSMutableArray*约束=[NSMutableArray];
NSMutableDictionary*视图=[[NSMutableDictionary alloc]init];
/*
标签一
*/
if(enableLabelOne){
[contentView addSubview:self.labelOne];
self.labelOne.translates自动调整大小GMaskintoConstraints=否;
[视图setObject:self.labelOne
福基:“_labelOne”];
[constraints addObjectsFromArray:[NSLayoutConstraints WithVisualFormat:@“V:[[u labelOne(44)]”
选项:0
指标:零
视图:视图]];
[constraints addObjectsFromArray:[NSLayoutConstraints WithVisualFormat:@“H:|-[[U labelOne]-|”
选项:0
指标:零
视图:视图]];
}
/*
标签二
*/
如果(启用Labeltwo){
[contentView addSubview:self.labelTwo];
self.labelTwo.translates自动调整大小GMaskintoConstraints=否;
[视图setObject:self.labelTwo
福基:“_labelTwo”];
[constraints addObjectsFromArray:[NSLayoutConstraint constraints WithVisualFormat:@“V:[[u labelTwo(44)]”
选项:0
指标:零
视图:视图]];
}
[constraints addObjectsFromArray:[NSLayoutConstraint constraints WithVisualFormat:@“H:|-[[U labelTwo]-|”
@implementation WBSCollapsingLabel
- (CGSize)intrinsicContentSize
{
if (self.isHidden) {
return CGSizeMake(UIViewNoIntrinsicMetric, 0.0f);
} else {
return [super intrinsicContentSize];
}
}
- (void)setHidden:(BOOL)hidden
{
[super setHidden:hidden];
[self updateConstraintsIfNeeded];
[self layoutIfNeeded];
}
@end
V:|-?-[Label1]-10-[Label2]-10-|
H:|-?-[Label1]-?-|
H:|-20-[Label2]-20-|
("|" is the real (outer) container)
V:|-?-[Label1]-0-[Label2HideableMarginContainer]-0-|
H:|-?-[Label1]-?-|
H:|-0-[Label2HideableMarginContainer]-0-|
("|" is Label2HideableMarginContainer)
V:|-10-[Label2]-10-|
H:|-20-[Label2]-20-|
public List<NSLayoutConstraint> SubConstraints { get; private set; }
private void ReadSubContraints()
{
var constraints = View.Constraints; // View: the Margin-Container NSView
if(constraints?.Any() ?? false)
{
SubConstraints = constraints.Where((NSLayoutConstraint c) => {
var predicate =
c.FirstAttribute == NSLayoutAttribute.Top ||
c.FirstAttribute == NSLayoutAttribute.Bottom ||
c.FirstAttribute == NSLayoutAttribute.Leading ||
c.FirstAttribute == NSLayoutAttribute.Trailing;
predicate &= ViewAndSubviews.Contains(c.FirstItem); // ViewAndSubviews: The View and View.Subviews
predicate &= ViewAndSubviews.Contains(c.SecondItem);
return predicate;
}).ToList();
}
}
let buttons = self.buttons!.filter { button in
return !button.hidden
}
constrain(buttons, replace: self.constraintGroup) { buttons in
let superview = buttons.first!.superview!
buttons.first!.left == superview.left
for var i = 1; i < buttons.count; i++ {
buttons[i].left == buttons[i-1].right + 10
}
buttons.last!.right == superview.right
}