如何在隐藏视图时使用自动布局移动其他视图?

本文翻译自:How to use auto-layout to move other views when a view is hidden?

I have designed my custom Cell in IB, subclassed it and connected my outlets to my custom class. 我在IB中设计了自定义Cell,将其子类化并将我的插座连接到我的自定义类。 I have three subviews in cell content which are: UIView (cdView) and two labels (titleLabel and emailLabel). 我在单元格内容中有三个子视图:UIView(cdView)和两个标签(titleLabel和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. 根据每行可用的数据,有时我想在我的单元格中显示UIView和两个标签,有时只有两个标签。 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. 我想要做的是设置约束,如果我将UIView属性设置为隐藏或我将从superview中删除它,两个标签将移动到左侧。 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). 我尝试将UIView前导约束设置为10px的Superview(单元格内容)和UILabels将10 px的约束引导到下一个视图(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;
}

I am hiding my cell.cdView and I would like the labels to move to the left however they are staying in the same position in Cell. 我隐藏了我的cell.cdView,我希望标签向左移动,但是它们在Cell中保持相同的位置。 I tried to remove cell.cdView from superview but it didn't work either. 我试图从superview中删除cell.cdView,但它也没有用。 I have attached image to clarify what I am about. 我附上图片来澄清我的意思。

细胞

I know how to do this programatically and I am not looking for that solution. 我知道如何以编程方式执行此操作,而我不是在寻找解决方案。 What I want is to set constraints in IB and I expect that my subviews will move dynamically if other views are removed or hidden. 我想要的是在IB中设置约束,并且如果删除或隐藏其他视图,我希望我的子视图将动态移动。 Is it possible to do this in IB with auto-layout? 是否可以在具有自动布局的IB中执行此操作?

.....

#1楼

参考:https://stackoom.com/question/1Dnm6/如何在隐藏视图时使用自动布局移动其他视图


#2楼

It is possible, but you'll have to do a little extra work. 这是可能的,但你必须做一些额外的工作。 There are a couple conceptual things to get out of the way first: 有一些概念性的东西可以先摆脱困境:

  • Hidden views, even though they don't draw, still participate in Auto Layout and usually retain their frames , leaving other related views in their places. 隐藏的视图,即使它们不绘制, 仍然参与自动布局,并且通常保留其框架 ,在其位置留下其他相关视图。
  • When removing a view from its superview, all related constraints are also removed from that view hierarchy. 从超级视图中删除视图时,也会从该视图层次结构中删除所有相关约束

In your case, this likely means: 在您的情况下,这可能意味着:

  • If you set your left view to be hidden, the labels stay in place, since that left view is still taking up space (even though it's not visible). 如果将左侧视图设置为隐藏,则标签会保留在原位,因为左侧视图仍占用空间(即使它不可见)。
  • If you remove your left view, your labels will probably be left ambiguously constrained, since you no longer have constraints for your labels' left edges. 如果删除左视图,则标签可能会受到模糊约束,因为您的标签左边缘不再有约束。

What you need to do is judiciously over-constrain your labels. 您需要做的是明智地过度约束您的标签。 Leave your existing constraints (10pts space to the other view) alone, but add another constraint: make your labels' left edges 10pts away from their superview's left edge with a non-required priority (the default high priority will probably work well). 单独留下现有约束(10pts空间到另一个视图),但添加另一个约束:使标签的左边缘与超级视图的左边缘相差10pts,具有非必需的优先级(默认的高优先级可能会很好)。

Then, when you want them to move left, remove the left view altogether. 然后,当您希望它们向左移动时,完全删除左视图。 The mandatory 10pt constraint to the left view will disappear along with the view it relates to, and you'll be left with just a high-priority constraint that the labels be 10pts away from their superview. 左视图的强制10pt约束将与其相关的视图一起消失,并且您将只留下一个高优先级约束,标签距其超视图10pts。 On the next layout pass, this should cause them to expand left until they fill the width of the superview but for your spacing around the edges. 在下一个布局过程中,这应该使它们向左扩展,直到它们填充超视图的宽度,但是围绕边缘的间距。

One important caveat: if you ever want your left view back in the picture, not only do you have to add it back into the view hierarchy, but you also have to reestablish all its constraints at the same time. 一个重要的警告:如果您希望将左侧视图放回到图片中,则不仅需要将其添加回视图层次结构中,而且还必须同时重新建立其所有约束 This means you need a way to put your 10pt spacing constraint between the view and its labels back whenever that view is shown again. 这意味着只要再次显示该视图,您就需要一种方法将视图及其标签之间的10pt间距约束放回去。


#3楼

将uiview和标签之间的约束连接为IBOutlet,并在设置hidden = YES时将优先级成员设置为较小的值


#4楼

Adding or removing constraints during runtime is a heavyweight operation that can affect performance. 在运行时添加或删除约束是一项可能影响性能的重量级操作。 However, there is a simpler alternative. 但是,有一个更简单的选择。

For the view you wish to hide, set up a width constraint. 对于要隐藏的视图,请设置宽度约束。 Constrain the other views with a leading horizontal gap to that view. 使用与该视图的前导水平间隙约束其他视图。

To hide, update the .constant of the width constraint to 0.f. 要隐藏, .constant宽度约束的.constant更新为0.f. The other views will automatically move left to assume position. 其他视图将自动向左移动以占据位置。

See my other answer here for more details: 有关详细信息,请参阅我的其他答案:

How to change label constraints during runtime? 如何在运行时更改标签约束?


#5楼

For the Googlers: building on Max's answer, to solve the padding issue that many have noticed I simply increased the height of the label and used that height as the separator instead of actual padding. 对于Google员工:在Max的答案基础上,为了解决许多人注意到的填充问题,我只是增加了标签的高度,并将该高度用作分隔符而不是实际的填充。 This idea could be expanded for any scenario with containing views. 对于包含视图的任何场景,可以扩展此想法。

Here's a simple example: 这是一个简单的例子:

IB截图

In this case, I map the height of the Author label to an appropriate IBOutlet : 在这种情况下,我将Author标签的高度映射到适当的IBOutlet

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

and when I set the height of the constraint to 0.0f , we preserve the "padding", because the Play button's height allows for it. 当我将约束的高度设置为0.0f ,我们保留“填充”,因为“ 播放”按钮的高度允许它。


#6楼

What I ended up doing was creating 2 xibs. 我最终做的是创建2个xib。 One with the left view and one without it. 一个是左视图,一个没有它。 I registered both in the controller and then decided which to use during cellForRowAtIndexPath. 我在控制器中注册了两个,然后决定在cellForRowAtIndexPath期间使用哪个。

They use the same UITableViewCell class. 它们使用相同的UITableViewCell类。 The downside is that there is some duplication of the content between the xibs, but these cells are pretty basic. 缺点是xib之间存在一些重复内容,但这些单元格非常基本。 The upside is that I don't have a bunch of code to manually manage removing view, updating constraints, etc. 好处是我没有一堆代码来手动管理删除视图,更新约束等。

In general, this is probably a better solution since they are technically different layouts and therefore should have different xibs. 一般来说,这可能是一个更好的解决方案,因为它们在技术上是不同的布局,因此应该有不同的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];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值