问题描述
假设我有这个 UIView
:
具有这些相对约束:
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *leftMarginConstraint;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *topMarginConstraint;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *widthConstraint;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *heightConstraint;
好的,现在让我们假设当用户单击该 UIButton
时,按钮应该移动到视图的右下角.我们可以轻松地使用两个约束来定义按钮和底部布局指南之间的底部空间以及按钮和视图右边缘之间的右侧空间(尾随空间).
Okay now let's assume that when the user click on that UIButton
the button should move to the bottom-right corner of the view. We can easily use two constraints defining bottom space between the button and the bottom layout guide and right space (trailing space) from the button and the right edge of the view.
问题在于 UIButton
已经有两个约束(左/上)和两个定义其宽度和高度的约束,因此我们不能添加两个新约束,因为它们会与另一个约束冲突那些.
The problem it's that the UIButton
already had two constraints (left/top) AND two contraints defining its width and its height so we can't add two new constraints because they would conflict with the other ones.
动画场景的简单常见情况,但它给我带来了一些问题.想法?
Simple and common situation for an animation scenario, but it causing me some problems. Ideas?
编辑
当用户点击 UIButton
时,我需要那个按钮:
When the user taps on the UIButton
, I need that the button:
- 将其标题更改为第二"
- 等待 1 秒并移动到右下角(移除顶部和左侧边距限制并添加底部和右侧边距限制)
- 将其标题更改为第三"
- 等待 1 秒,然后移动到右上角(移除下边距限制并添加上边距约束)
我真的一定要使用这个乱七八糟的代码吗?
Am I seriously bound to use this messy code?
@implementation ViewController
{
NSLayoutConstraint *_topMarginConstraint;
NSLayoutConstraint *_leftMarginConstraint;
NSLayoutConstraint *_bottomMarginConstraint;
NSLayoutConstraint *_rightMarginConstraint;
}
- (IBAction)buttonPressed:(id)sender
{
UIButton *button = sender;
// 1.
[sender setTitle:@"Second" forState:UIControlStateNormal];
// 2.
double delayInSeconds = 1.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
[button removeConstraints:@[self.leftMarginConstraint, self.topMarginConstraint]];
_bottomMarginConstraint = [NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeBottom
relatedBy:0 toItem:button
attribute:NSLayoutAttributeBottom
multiplier:1
constant:20];
[self.view addConstraint:_bottomMarginConstraint];
_rightMarginConstraint = [NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeRight
relatedBy:0 toItem:button
attribute:NSLayoutAttributeRight
multiplier:1
constant:20];
[self.view addConstraint:_rightMarginConstraint];
[UIView animateWithDuration:1 animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
// 3.
[sender setTitle:@"Third" forState:UIControlStateNormal];
// 4.
double delayInSeconds = 1.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
[button removeConstraint:_bottomMarginConstraint];
_topMarginConstraint = [NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeTop
relatedBy:0 toItem:button
attribute:NSLayoutAttributeTop
multiplier:1
constant:20];
[UIView animateWithDuration:1 animations:^{
[self.view layoutIfNeeded];
}];
});
}];
});
}
严重吗?:D
推荐答案
删除左右约束,添加上下约束,然后在动画块中调用layoutIfNeeded动画到新位置.第二种方法 move2 中的代码可以嵌入到 move1 的完成块中,但我发现如果将这两个移动放在不同的方法中会更容易阅读(它确实需要添加另一个属性 bottomCon):
Delete the left and top constraints, add the bottom and right constraints, then call layoutIfNeeded in an animation block to animate to the new position. The code in the second method, move2 could be embedded in the completion block of move1, but I find it easier to read if you keep the two moves in separate methods (it does necessitate the addition of another property, bottomCon):
- (IBAction)move1:(UIButton *)sender {
[sender setTitle:@"Second" forState:UIControlStateNormal];
[sender layoutIfNeeded];
[self.view removeConstraints:@[self.leftCon,self.topCon]];
self.bottomCon = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeBottom relatedBy:0 toItem:self.button attribute:NSLayoutAttributeBottom multiplier:1 constant:20];
[self.view addConstraint:self.bottomCon];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeRight relatedBy:0 toItem:self.button attribute:NSLayoutAttributeRight multiplier:1 constant:20]];
[UIView animateWithDuration:1 delay:1.0 options:0 animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
[sender setTitle:@"Third" forState:UIControlStateNormal];
[self move2];
}];
}
-(void)move2 {
[self.view removeConstraint:self.bottomCon];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeTop relatedBy:0 toItem:self.button attribute:NSLayoutAttributeTop multiplier:1 constant:-20]];
[UIView animateWithDuration:1 delay:1.0 options:0 animations:^{
[self.view layoutIfNeeded];
} completion:nil];
}
这篇关于自动布局、约束和动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!