使用自动布局隐藏视图并重新定位其他视图

Posted

技术标签:

【中文标题】使用自动布局隐藏视图并重新定位其他视图【英文标题】:Hide View and reposition other View with Autolayouts 【发布时间】:2014-04-01 17:43:27 【问题描述】:

各位,

我有一个包含多个信息的配置文件视图。其中一些不必设置,例如传记。因此,根据它的设置,我想隐藏传记视图(结帐截图)并重新定位 UserData 视图和 ActivityData 视图并更改其超级视图的大小以填充传记视图所产生的空间。

这是我的 TableViewHeader 的实际结构:

我必须关心的另一点是,UILabel 必须是多行的并适合其内容。

所以我的问题:

如何重新定位 UserData 和 ActivityData 视图以填充 隐藏的 BiografieView 创造的空间? 如何制作传记 视图高度适合 UILabel 文本吗?

请记住,我使用的是自动布局。所以我必须使用约束来修改位置吗?

说实话.. 基本上它应该像 Instagram 一样,添加一个传记。我希望我说清楚了我想要什么..

编辑 1

我已经尝试过您的建议 Damien,但没有任何改变:

    NSLog(@"Height %f, Width %f", self.labelBiografie.frame.size.height, self.labelBiografie.frame.size.width);

if ([self.profileUser objectForKey:kGSUserBiografieKey]) 
    self.labelBiografie.text = [self.profileUser objectForKey:kGSUserBiografieKey];
    [self.labelBiografie sizeToFit];
else
    [self.labelBiografie setHidden:YES];
    [self.countContainer setConstraintConstant:-self.labelBiografie.frame.size.height forAttribute:NSLayoutAttributeCenterY];
    [self.tableHeaderViewChildVIew setConstraintConstant:-self.labelBiografie.frame.size.height forAttribute:NSLayoutAttributeHeight];
    self.tableView.tableHeaderView = self.tableHeaderViewChildVIew;

编辑 2:

使用这个项目 (UIView-UpdateAutoLayoutConstraints ) 我在方法上遇到以下错误:

第 56 行:[self hideView:hidden byAttribute:NSLayoutAttributeHeight];

第 85 行:[self setConstraintConstant:0 forAttribute:attribute];

第 23 行:

[self.superview addConstraint: [NSLayoutConstraint constraintWithItem:self attribute:attribute relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:constant]];

错误:

    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x8c1b8e0 V:|-(0)-[UIButton:0x8c6fb40]   (Names: '|':UIView:0x8c6f630 )>",
    "<NSLayoutConstraint:0x8c19dc0 V:[UIButton:0x8c6fb40(100)]>",
    "<NSLayoutConstraint:0x8c1d740 V:[UIButton:0x8c6fb40]-(NSSpace(8))-[UILabel:0x8c70900]>",
    "<NSLayoutConstraint:0x8c20df0 V:[UILabel:0x8c70900]-(NSSpace(8))-[UIView:0x8c16a00]>",
    "<NSLayoutConstraint:0x8c20fa0 V:[UIView:0x8c16a00(40)]>",
    "<NSLayoutConstraint:0x8c23790 V:[UIView:0x8c16a00]-(0)-|   (Names: '|':UIView:0x8c6f630 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x8c78e60 h=--& v=--& V:[UIView:0x8c6f630(217)]>",
    "<NSLayoutConstraint:0x8c5d000 V:[UILabel:0x8c70900(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x8c20df0 V:[UILabel:0x8c70900]-(NSSpace(8))-[UIView:0x8c16a00]>

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

这个错误显示在开箱即用的演示项目上,在我的项目上,当我隐藏视图时它也会返回..

【问题讨论】:

【参考方案1】:

我建立了一个类别来回答这个我也遇到过的问题: Hide autolayout UIView : How to get existing NSLayoutConstraint to update this one

编辑:

如果您使用自动布局,请不要再使用 view.frame 并且不要忘记像这样设置所有自动布局视图:

myView.translatesAutoresizingMaskIntoConstraints = NO;

使用这个类别https://github.com/damienromito/UIView-UpdateAutoLayoutConstraints

if(!user.biografie && user.biografie.lenght == 0)

     [biografieLabel setConstraintConstant:0 forAttribute:NSLayoutAttributeHeight];
else

     biografieLabel.text = user.biografie;

【讨论】:

第二季度你有答案了吗? 您确定已使用自动布局定位所有视图吗?如果 UserData 和 ActivityData 视图有框架,这是正常的,它不起作用。不要忘记将所有视图设置为自动布局视图:UserData.translatesAutoresizingMaskIntoConstraints = NO; ActivityData.translatesAutoresizingMaskIntoConstraints = NO;最重要的是,创建约束。 enharmonichq.com/tutorial-auto-layout-part-2 好的,我只以编程方式使用自动布局。我将尝试为您编写一个示例(也许今晚)。 tableviewheader 不是问题。 我编写了一个示例...我学到了一些技巧,因为您想要的行为非常复杂。 github.com/damienromito/UIView-UpdateAutoLayoutConstraints 我实现了一种隐藏/显示视图的方法。在这个演示中它不能完美地工作,但你可以在其他情况下使用它。 是的,我的错,将动态标签的约束设置为“0”完全没用 (set label.text = @"") 。我更新了演示。如果你一切都好,请验证这个答案;)【参考方案2】:

对于您的问题二,第一个解决方案是在 uilabel 与其容器的高度(BiografieView)之间设置高度限制。

NSLayoutConstraint *constraint = [NSLayoutConstraint
                                  constraintWithItem:biografieView /// change here
                                  attribute:NSLayoutAttributeHeight
                                  relatedBy:NSLayoutRelationEqual
                                  toItem:biografieLabel  /// change here
                                  attribute:NSLayoutAttributeHeight
                                  multiplier:1
                                  constant:0];
[view addConstraint:constraint];

别忘了设置 uilabel.numberOfLine = 0 , 这个高度会自动更新

BUT,BUT,BUT...*(为您的情况提供更好的解决方案) 如果您的传记视图中只有一个 uilabel,请移除此容器。 uilabel也是uiview,你不会再有这个问题了。

【讨论】:

我明天必须检查一下

以上是关于使用自动布局隐藏视图并重新定位其他视图的主要内容,如果未能解决你的问题,请参考以下文章

使用自动布局调整同级视图的大小时,使用子视图重新定位 UIView 不起作用

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

iOS 自动布局约束:忽略隐藏或零尺寸视图?

自动布局:如何隐藏包含子视图的 UIView?

添加 UIView 并使用自动布局重新计算约束

使用自动布局删除视图并重新排列其余部分