I have designed my custom Cell in IB, subclassed it and connected my outlets to my custom class. I have three subviews in cell content which are: UIView (cdView) and two labels (titleLabel and emailLabel). Depending on data available for each row, sometimes I want to have UIView and two labels displayed in my cell and sometimes only two labels. What I am trying to do is to set constraints that way if I set UIView property to hidden or I will remove it from superview the two labels will move to the left. I tried to set UIView leading constraint to Superview (Cell content) for 10px and UILabels leading Constraints for 10 px to the next view (UIView). Later in my code

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(IndexPath *)indexPath {
    
    // ...

    Record *record = [self.records objectAtIndex:indexPath.row];
    
    if ([record.imageURL is equalToString:@""]) {
         cell.cdView.hidden = YES;
    }
}

我把手机藏起来了。cdView和我想要标签移动到左边,但他们在细胞中保持相同的位置。我试着移除细胞。cdView从superview,但它也没有工作。我附上了图片,以澄清我是什么。

我知道如何通过编程来做到这一点,我不是在寻找解决方案。我想要的是在IB中设置约束,我希望如果其他视图被删除或隐藏,我的子视图将动态移动。有可能在IB自动布局中做到这一点吗?

.....

当前回答

这是一个老问题,但我仍然希望它能有所帮助。来自Android,在这个平台上,你有一个方便的方法isVisible隐藏它从视图,但也没有考虑框架时,自动布局绘制视图。

使用extension和“extend”uiview,你可以在ios中做类似的功能(不确定为什么它不在UIKit中)这里是swift 3中的实现:

    func isVisible(_ isVisible: Bool) {
        self.isHidden = !isVisible
        self.translatesAutoresizingMaskIntoConstraints = isVisible
        if isVisible { //if visible we remove the hight constraint 
            if let constraint = (self.constraints.filter{$0.firstAttribute == .height}.first){
                self.removeConstraint(constraint)
            }
        } else { //if not visible we add a constraint to force the view to have a hight set to 0
            let height = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal , toItem: nil, attribute: .notAnAttribute, multiplier: 0, constant: 0)
            self.addConstraint(height)
        }
        self.layoutIfNeeded()
    }

其他回答

只需使用UIStackView和一切将工作正常。 不需要担心其他约束,UIStackView将自动处理空间。

我最终创建了2个xib。一个有左视图,一个没有。我在控制器中注册了这两个,然后决定在cellForRowAtIndexPath期间使用哪个。

它们使用相同的UITableViewCell类。缺点是在xib之间有一些重复的内容,但是这些单元格非常基本。好处是我不需要一堆代码来手动管理删除视图、更新约束等。

一般来说,这可能是一个更好的解决方案,因为它们在技术上是不同的布局,因此应该有不同的xib。

[self.table registerNib:[UINib nibWithNibName:@"TrackCell" bundle:nil] forCellReuseIdentifier:@"TrackCell"];
[self.table registerNib:[UINib nibWithNibName:@"TrackCellNoImage" bundle:nil] forCellReuseIdentifier:@"TrackCellNoImage"];

TrackCell *cell = [tableView dequeueReusableCellWithIdentifier:(appDelegate.showImages ? @"TrackCell" : @"TrackCellNoImage") forIndexPath:indexPath];

最简单的解决方案是使用UIStackView(水平)。添加到堆栈视图:带标签的第一个视图和第二个视图。 然后将first view的isHidden属性设置为false。 所有约束都将自动计算和更新。

在本例中,我将Author标签的高度映射到适当的IBOutlet:

@property (retain, nonatomic) IBOutlet NSLayoutConstraint* authorLabelHeight;

当我将约束的高度设置为0.0f时,我们保留了“填充”,因为播放按钮的高度允许它。

cell.authorLabelHeight.constant = 0;

为了帮助别人,我构建了一个使用可视格式约束的helper类。我在我当前的应用程序中使用它。

AutolayoutHelper

它可能有点适合我的需要,但您可能会发现它很有用,或者您可能想修改它并创建自己的帮助器。

我必须感谢Tim的回答,这个关于UIScrollView和本教程的回答。