自动布局确定子视图的大小

时间:2015-04-18 01:43:45

标签: ios objective-c autolayout

我有一个KSSection UIView子类,我试图用它来折叠/扩展不同的部分。它有一个名为IBOutlet的子视图(由content设置)。 content的大小由多个可变大小的子视图(UILabelUIImageView等)确定。

目前,我将content的前导空格和尾随空格固定到父KSSection,将其垂直居中对齐,并添加remove at runtime约束,其高度为{ {1}}和content相等。如果我禁用section,一切都很有效 - 除非我无法解除视图。

如何计算remove at runtime的大小,以用作content的{​​{1}}?到目前为止,我有以下代码段,但对intrinsicContentSize的调用始终会为这两个属性返回KSection

intrinsicContentSize

修改

很抱歉澄清它实际上正在为UIViewNoIntrinsicMetric的两个维度返回@implementation SKContainer - (CGSize)intrinsicContentSize { if (self.collapsed) return CGSizeZero; else return [self.content intrinsicContentSize]; } - (void)layoutSubviews { [super layoutSubviews]; [self invalidateIntrinsicContentSize]; } - (void)setCollapsed:(BOOL)collapsed { if (_collapsed != collapsed) { _collapsed = collapsed; [self invalidateIntrinsicContentSize]; } } @end

附加样本:http://cl.ly/2F3s3X3y2U1H

3 个答案:

答案 0 :(得分:1)

您滥用-intrinsicContentSize,无论是为什么要调用它,还是尝试为您的视图类实现它。该方法用于返回其性质和内容“固有”的大小。它不能依赖于其他视图,其他约束等。它也与视图的当前大小无关,因为视图可以通过其他约束从其内在大小压缩或拉伸。

您应该使用约束来使视图依赖于其折叠状态及其子视图的大小(由于其他约束与后代视图的内在大小(如果有的话)相结合)。

例如,假设您希望视图在垂直方向上折叠,则可能存在一些约束,这些约束始终将内容子视图固定到顶部,前导和尾部边缘。如果您的视图已折叠,则您将有一个约束使其高度为零。您将视图的底部限制在内容视图的底部。内容视图将具有其正常高度,但由于其superview的高度为零,因此将全部剪切掉。

另一方面,如果您的视图未折叠,则会删除视图上的高度约束,并添加一个约束,将视图的底部连接到内容视图的底部。

答案 1 :(得分:1)

好的,所以我之前的回答是不必要的。我最终做的是:

首先,我完全删除了剖面视图,只留下普通的香草内容视图来扮演该部分的角色。 (剖面视图只是添加了一个额外的复杂层。)然后我将剖面视图高度的优先级降低到250,然后运行项目。普雷斯托!现在,剖面视图会自动扩展,由其中的标签约束驱动。

其次,这是我如何崩溃和扩张。我保留了两个约束的出口:截面高度约束,以及内部约束的高度堆栈中的最后一个约束。然后我的展开/折叠代码如下所示:

- (IBAction)toggleButtonSelector:(id)sender
{
    self.collapsed = !self.collapsed;
    if (self.collapsed) {
        self.sectionHeightConstraint.constant = 10; // or whatever height you like
        self.sectionHeightConstraint.priority = 999;
        [NSLayoutConstraint deactivateConstraints:@[self.bottomInternalConstraint]];
    } else {
        self.sectionHeightConstraint.priority = 250;
        [NSLayoutConstraint activateConstraints:@[self.bottomInternalConstraint]];

    }
}

你知道,我们需要克服内部堆栈约束的愿望来保持扩展,所以我们删除其中一个约束以便崩溃,我们将高度约束设置为一个小数字并提高其优先级。为了扩展,我们反过来说:我们恢复缺少的内部约束,并再次降低整个部分高度约束的优先级。

编辑这个实现的一个非常酷的副产品是我们现在可以通过在该方法的末尾附加这些代码行来设置崩溃/扩展效果的动画:

    [UIView animateWithDuration:1 animations:^{
        [self.view layoutIfNeeded];
    }];

答案 2 :(得分:0)

使用来自@ken和@matt的解决方案我的最终代码(仍然使用SKContainer)是:

@interface SKContainer ()

@property (nonatomic, strong) IBOutlet NSLayoutConstraint *expandedLayoutConstraint;
@property (nonatomic, strong) IBOutlet NSLayoutConstraint *collapsedLayoutConstraint;

@end

@implementation SKContainer

- (void)setCollapsed:(BOOL)collapsed
{
    if (_collapsed != collapsed)
    {
        _collapsed = collapsed;

        [self removeConstraint:collapsed ? self.expandedLayoutConstraint : self.collapsedLayoutConstraint];
        [self addConstraint:collapsed ? self.collapsedLayoutConstraint : self.expandedLayoutConstraint];
    }
}

@end

expandedLayoutConstraintcontent视图的高度约束相同,而collapsedLayoutConstraint0优先级200约束。