如何隐藏不适合可用 space 的 UIView?

How to hide a UIView that doesn't fit in available space?

有一个包含 4 个元素的堆栈视图。

每个元素的水平内容压缩阻力优先级都是 1000,除了一个:

A(1000) - B(1000) - C(999) - D(1000)

有很多space,没有问题,各取所需。但是,当 space 被限制时,C 视图首先水平收缩以将 space 给其他视图。

它可能会缩小直到看不见:

A(1000) - B(1000) - - D(1000)

但是,虽然看不见,但B和D之间的距离是A和B之间space的两倍。因为C没有被隐藏,只是缩小了。

有什么方法可以检测到视图已经缩小了吗?这样才能真正隐藏起来。

PD:这个视图在 UITableViewCell 中,而不是在 UIViewController 中。该单元格没有 didLayoutSubviews 方法,我尝试在 layoutSubviews 中这样做:

- (void)layoutSubviews
{
    [super layoutSubviews];
    // Truly hide it if is not visible anymore because there is no space.
    self.view.hidden = self.view.frame.size.width == 0;
}

但是没用,知道吗?

这个怎么样。

代码如下。这只是一个示例,需要正确的故事板配置。

@interface ViewController ()

@property (weak, nonatomic) IBOutlet NSLayoutConstraint * trailingConstraint;
@property (weak, nonatomic) IBOutlet UIView             * blackView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint * blackViewTrailingConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint * blackViewWidthConstraint;

@property (nonatomic) BOOL preventLoop;

@end

@implementation ViewController

- (void)viewDidLoad {

    super.viewDidLoad;

    [self.blackView addObserver:self
             forKeyPath:@"bounds"
                options:0
                context:nil];

}

- ( void ) observeValueForKeyPath: ( NSString     * ) keyPath
             ofObject: ( id             ) object
               change: ( NSDictionary * ) change
              context: ( void         * ) context
{
    if ( ! self.preventLoop ) {

        self.preventLoop = YES;

        if ( self.blackView.bounds.size.width < 10 ) {

            self.blackViewWidthConstraint.constant = 0;
            self.blackViewTrailingConstraint.constant = 0;

        } else {

            self.blackViewTrailingConstraint.constant = 40;

        }

        self.preventLoop = NO;

    }

}

- (IBAction)squashButtonAction:(id)sender {

    self.trailingConstraint.constant += 10;
    self.blackViewWidthConstraint.constant = MAX ( 0, self.blackViewWidthConstraint.constant - 10 );

}

- (IBAction)resetButtonAction:(id)sender {

    self.trailingConstraint.constant = 20;
    self.blackViewWidthConstraint.constant = 150;

}

@end

想法是使用键值观察来检测边界大小何时低于阈值;在这种情况下为 10。当发生这种情况时,相关视图(此处为黑色)的宽度和尾随约束都将设置为 0。此处的宽度很明显,尾随约束是黑色视图和最后一个黄色视图之间的 space .这样你就不会得到两倍的 space.

由于您更改了观察者内部的值,因此您需要一些逻辑来防止其循环,如您在代码中所见。

黑色视图的宽度约束以及紫色视图的拖尾约束用于模拟视图的压缩,直到黑色视图不再足够space。在您的特定情况下,您可能需要以不同的方式连接它,但这可以完成工作,并且您有一个很好的工作示例来说明这个想法。

编辑

给猫剥皮的方法有很多种……这是另一种更简单的方法。这混合了您最初尝试和我最初回答的想法。除了使用观察者之外,您还可以在其中一个布局消息中执行相同的操作,如下所示。

我认为你的尝试和我的建议之间的最大区别只是添加一个尾随约束(blackViewTrailingConstraint 在我的代码中)然后用它来压缩尾随 space 到 0在适当的时候。

无论如何,这是在没有观察者的情况下完成相同任务的代码

- ( void ) viewWillLayoutSubviews {

    // you could also use ...

    // if ( self.blackView.bounds.size.width < 5 ) {

    // ... here but it is more correct to use the width
    // constaint and not the actual width here as you
    // and set the constaint and the width only updates
    // once layout completes
    if ( self.blackViewWidthConstraint.constant < 5 ) {

        self.blackViewWidthConstraint.constant = 0;
        self.blackViewTrailingConstraint.constant = 0;
        
    } else {

        self.blackViewTrailingConstraint.constant = 40;

    }

}