使用 AutoLayout 时显示和隐藏视图

Show and hide views when using AutoLayout

我有一些视图,我必须删除一个 UIView 并让所有其他视图在没有此视图的情况下重新排列。我通常通过创建多个具有不同权重的约束来做到这一点,所以当我删除 FromSuperView 时,所有其他具有较低权重的约束开始工作并且一切都按照我的需要重新排列。

它工作得很好,但现在我必须显示和隐藏视图,但是当我删除 FromSuperView 时,该视图及其所有约束都消失了...我不知道该怎么做...我可以更改宽度和高度对于我想隐藏的视图,约束为零...但问题是我必须在代码中硬编码高度,我不喜欢它...

隐藏和显示 UIView 的最佳方式是什么?类似于 "Installed" 属性 的东西,您可以在 IB 中设置,但可以从代码中设置。

当你从超级视图中删除视图时你失去了约束,你基本上使它可用于视图中的任何对象并且这样你必须编写一些方法来添加到其他视图(以编程方式添加约束) 或再次删除它。

根据我的经验,隐藏视图可以使用 约束动画查看自身动画 并将其向左、向右、向上抛出或向下。此外,如果它在用户交互中不可用,您可以使用 self.view.hidden = trueself.view.userInteractionEnabled = false 禁用它。在更新视图时使用 dispatch_async(),apple 喜欢代码标准的人 :)。

用动画隐藏视图本身:

            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.view.hidden = true // Or userInteractionEnable = false
                UIView.animateWithDuration(1.0, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
                    self.reportView.alpha = 0
                    }, completion: nil)
            })

隐藏带约束的视图:

您需要创建约束 IBOutlet 才能在动画中使用常量。

        self.someView.constant = -205 // Throw it off canaves
        UIView.animateWithDuration(1.0, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
            self.view.layoutIfNeeded()
            }, completion: { (finished: Bool)-> Void in
                self.someView.hidden = true
        })

要使它出现,只需反向进行相同的思考即可。但不要 removeFromSuperView(),除非你试图将它附加到 First Responder 或类似的东西。

我不确定是否适合您的问题,但我做了几次,以确保您要隐藏的视图位于容器中。这样的容器应该有高度和宽度限制(这是你可能不喜欢的地方)。然后,您在相关视图控制器中为这些约束中的每一个创建 IBOutlets(从故事板中的约束控制拖动)。最后,您可以将约束的初始值保存在 viedidload 中,稍后使用它从零切换到该值,无论它是什么。

如果目标是 iOS 9 及以上,您可以尝试 UIStackView。

我们可以考虑保留约束的一种方法是在 UIView 上创建一个类别。

@interface UIView (ConstraintsPreserving)

@property (nonatomic, strong) NSMutableArray * preservedConstraints;

-(void)removeFromSuperViewPreservingConstriants;
-(void)addToSuperViewPreservingConstriants:(UIView *)superView;

@end

#import <objc/runtime.h>

@implementation UIView (ConstraintsPreserving)

@dynamic preservedConstraints;

-(void)setPreservedConstraints:(NSMutableArray *)object {
    objc_setAssociatedObject(self, @selector(preservedConstraints), object, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSMutableArray *)preservedConstraints {
    return objc_getAssociatedObject(self, @selector(preservedConstraints));
}

-(void)removeFromSuperViewPreservingConstriants
{
    if(!self.superview) return;

    self.preservedConstraints = [NSMutableArray new];
    [self.preservedConstraints addObjectsFromArray:[self constraints]];

    for (NSLayoutConstraint * constraint in self.superview.constraints) {
        if([constraint.firstItem isEqual:self] || [constraint.secondItem isEqual:self])
            [self.preservedConstraints addObject:constraint];
    }
    [self removeFromSuperview];
}

-(void)addToSuperViewPreservingConstriants:(UIView *)superView
{
    if(self.superview) return;

    [superView addSubview:self];
    [superView addConstraints:self.preservedConstraints];
    self.preservedConstraints = nil;
}

@end

PS:这强烈地捕获了约束,通过捕获这些约束中涉及的所有视图。

所以,我最终为要隐藏的视图创建了 IBOutlets。我将宽度和高度约束设置为零,这样我就可以隐藏视图。我还设置了多个 IBOutlets 并更改了此约束的优先级,以便我可以重新安排内容...

这是我发现的最好的方法。