如何隐藏不适合可用 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;
}
}
有一个包含 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;
}
}