我在自定义类中有一个方法,可以调整和约束自定义UIView:
-(void) sizeAndConstrainHeaderView:(HeaderView *)headerView inView:(UIView *)view {
CGFloat height;
// code to calculate height is omitted.
headerView.heightConstraint = [NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:height];
headerView.translatesAutoresizingMaskIntoConstraints = NO;
if (!headerView.isConstrained) {
[view addConstraint:[NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
[view addConstraint:[NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
[view addConstraint:[NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:view.frame.size.width]];
[headerView addConstraint:headerView.heightConstraint];
headerView.isConstrained = YES;
}
headerView.heightConstraint.constant = height;
// trying everything here to get the constraint to update
[headerView setNeedsUpdateConstraints];
[headerView layoutIfNeeded];
[view setNeedsUpdateConstraints];
[view layoutIfNeeded];
NSLog(@"height constraint constant: %f", headerView.heightConstraint.constant);
}
我在视图控制器中这样称呼它:
[customClass sizeAndConstrainHeaderView:_headerView inView:self.view];
由于多次调用(在检索数据之前,一次之后),因此存在是否添加约束的标志。然后,无论如何,高度常数被设置为计算的高度。但无论我怎么称呼,在视图或自定义视图中,视图的高度都不会改变,我无法弄清楚原因。其他限制工作正常。日志显示高度已更改。但这种观点并没有反映出来。我确实知道,因为我调试了视图层次结构并且可以看到它没有更新。
答案 0 :(得分:1)
你说
由于多次调用(在检索数据之前,一次之后),因此存在是否添加约束的标志。
但是您的方法是在每次调用上执行此操作:
headerView.heightConstraint = [NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:height];
因此,在每次调用时,您都会创建一个新约束,将其存储在headerView.heightConstraint
中,并将新约束设置为常量。
但是,您只在第一次调用方法时安装此新约束。
也许您应该只在第一次调用时创建约束:
-(void) sizeAndConstrainHeaderView:(HeaderView *)headerView inView:(UIView *)view {
CGFloat height;
// code to calculate height is omitted.
if (!headerView.isConstrained) {
headerView.translatesAutoresizingMaskIntoConstraints = NO;
[view addConstraint:[NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
[view addConstraint:[NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
[view addConstraint:[NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:view.frame.size.width]];
headerView.heightConstraint = [NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:height];
[headerView addConstraint:headerView.heightConstraint];
headerView.isConstrained = YES;
}
headerView.heightConstraint.constant = height;
}
答案 1 :(得分:0)
这里可能存在很多问题,因为Autolayout是一件复杂的事情。但是我会立即通过您对高度约束的初步声明来解决问题。你声明了CGFloat的高度 - 但你没有给它一个值。然后将其设置为headerView的height约束属性的常量。所以看起来你把0作为一个常量,可能会使约束变得无用。
您是否在视图中使用笔尖或故事板?如果是这样,您可以使用IBOutlet将要影响的约束直接拖到视图类中。这是在运行时以编程方式更改约束常量的最常用方法。只需将其作为类属性拖放,然后像这样更改它的.constant值。
另一个问题可能是超级视图中的其他限制因素与此问题发生冲突,而Autolayout已经决定优先考虑另一个限制因素。如果存在与约束的冲突,您将获得有关它的大量日志消息,因此请密切注意这些。
以下是我通常的程序化约束,工作正常:
NSMutableArray *constraints = [NSMutableArray array];
NSString *verticalConstraint = [NSString stringWithFormat:@"V:|-%i-[headerView(%i)]-%i-|", topBuffer, height, bottomBuffer];
NSString *horizontalConstraint = [NSString stringWithFormat:@"H:|-%i-[headerView(%i)]-%i-", leading, width, trailing];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:verticalConstraint options:0 metrics:nil views:NSDictionaryOfVariableBindings(headerView)]];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:horizontalConstraint options:0 metrics:nil views:NSDictionaryOfVariableBindings(headerView)]];
[self addConstraints:constraints];
答案 2 :(得分:0)
每当我使用这些调用时,我都不会将nil作为toItem参数传递。传递nil意味着约束与任何事物无关,这使得任何高度/宽度计算都无意义。警告:我通常不使用constraintWithItem调用,尽可能更容易使用visualFormat api。