使用自动布局调整同级视图的大小时,使用子视图重新定位 UIView 不起作用
Posted
技术标签:
【中文标题】使用自动布局调整同级视图的大小时,使用子视图重新定位 UIView 不起作用【英文标题】:Reposition of UIView with subviews not working when resizing a sibling view with auto layout 【发布时间】:2014-09-08 07:58:15 【问题描述】:我有两个视图正在尝试使用自动布局调整大小/重新定位。
我设置了以下约束:
红色视图:
要查看的顶部空间:0 superview 的尾随和前导空格:0 高度等于:100蓝色视图:
红色视图的顶部空间:0 superview 的尾随和前导空格:0 高度等于:100两个视图都是self.view
的子视图。蓝色视图有一个UILabel
作为子视图(屏幕截图中未显示)。
我想要做的是改变红色视图的大小(带动画)并让蓝色视图跟随大小变化:
- (IBAction)resizeButtonPressed:(UIButton*)sender
[UIView animateWithDuration:0.25 animations:^
if (sender.selected)
self.redViewHeightConstraint.constant = 100; // collapse
else
self.redViewHeightConstraint.constant = 200; // expand
[self.view layoutIfNeeded];
];
sender.selected = !sender.selected;
动画有效,红色视图的大小发生变化。然而,蓝色视图永远不会改变位置,即使它对红色视图的底部有限制。
我尝试添加[self.blueView layoutIfNeeded]
,甚至同时添加[self.view setNeedsUpdateConstraints]
和[self.blueView setNeedsUpdateConstraints]
,但没有任何区别。
奇怪的是,如果我从蓝色视图中删除标签,一切都会按预期工作。一旦我再次添加它,蓝色视图就会保持静止。标签是否有任何约束都没有关系。
【问题讨论】:
【参考方案1】:这是一个完整的实现:
@interface ViewController ()
@property(nonatomic, strong) NSLayoutConstraint* redViewHeightConstraint;
@end
@implementation ViewController
- (void)viewDidLoad
[super viewDidLoad];
UIView* redView = [[UIView alloc] init];
UIView* blueView = [[UIView alloc] init];
redView.translatesAutoresizingMaskIntoConstraints = NO;
blueView.translatesAutoresizingMaskIntoConstraints = NO;
redView.backgroundColor = [UIColor redColor];
blueView.backgroundColor = [UIColor blueColor];
NSDictionary* views = NSDictionaryOfVariableBindings(redView, blueView);
[self.view addSubview:redView];
[self.view addSubview:blueView];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[redView]|"
options:0
metrics:nil
views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[blueView]|"
options:0
metrics:nil
views:views]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:redView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1
constant:0]];
self.redViewHeightConstraint = [NSLayoutConstraint constraintWithItem:redView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:0
constant:100];
[self.view addConstraint:self.redViewHeightConstraint];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:blueView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:redView
attribute:NSLayoutAttributeBottom
multiplier:1
constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:blueView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:0
constant:100]];
UILabel* label = [[UILabel alloc] init];
label.text = @"label";
label.translatesAutoresizingMaskIntoConstraints = NO;
[blueView addSubview:label];
[blueView addConstraint:[NSLayoutConstraint constraintWithItem:label
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:blueView
attribute:NSLayoutAttributeCenterX
multiplier:1
constant:0]];
[blueView addConstraint:[NSLayoutConstraint constraintWithItem:label
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:blueView
attribute:NSLayoutAttributeCenterY
multiplier:1
constant:0]];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:@selector(resizeButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:@"Expand" forState:UIControlStateNormal];
[button setTitle:@"Collapse" forState:UIControlStateSelected];
button.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:button];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:button
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:blueView
attribute:NSLayoutAttributeBottom
multiplier:1
constant:30]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:button
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1
constant:0]];
- (IBAction)resizeButtonPressed:(UIButton*)sender
[UIView animateWithDuration:0.25 animations:^
if (sender.selected)
self.redViewHeightConstraint.constant = 100; // collapse
else
self.redViewHeightConstraint.constant = 200; // expand
[self.view layoutIfNeeded];
];
sender.selected = !sender.selected;
@end
【讨论】:
【参考方案2】:我也遇到了同样的问题。
我通过在动画块(CGRect frame = self.label.frame;
)之前保存标签的帧并在动画块中再次设置标签的帧(self.label.frame = frame;
)来解决它
【讨论】:
我真的很想避免操纵框架,因为在使用自动布局时我们不应该这样做。此外,我想在这里了解我的问题的原因。 如何在blueView上添加标签?你添加了什么约束?以上是关于使用自动布局调整同级视图的大小时,使用子视图重新定位 UIView 不起作用的主要内容,如果未能解决你的问题,请参考以下文章