参考
如何对使用了autolayout的UIView添加动画
如何解决IOS 动画中 Autolayout 与View Transforms的冲突
How do I adjust the anchor point of a CALayer, when Auto Layout is being used?
AutoLayout相关概念介绍和动画demo
How do I adjust the anchor point of a CALayer, when Auto Layout is being used?
当我们对一个UIView使用了autolayout自动布局之后,也就意味着我们放弃了传统的通过设置view的frame等方式手动的修改、确定这个view的位置、尺寸属性。甚至从某种程度上讲,我们应该忘记view的frame属性:它的确定不再取决于我(手动的直接修改),而是通过我们在 storyboard或者code中提供的约束条件(constraints),通过一个自动布局引擎(苹果为autolayout采用的是 Cassowary布局引擎),计算出这个view的frame。因此我们可以认为使用了autolayout的view的frame属性是一个只读的属性。在代码里认为的改动这个view的frame并不能对这个view的frame产生真正的效果(事实也确实如此)。
现在问题就来了,在以前我们经常通过对一个view的frame的修改产生view移动的动画效果,那么在使用了autolayout的view世界中我 们该如何实现相同的效果呢?答案是,我们“将计就计”,通过改变这个view上的某个约束constraint然后在uiview的animation block中触发layout来实现。
下面看一些简单的情况
for (NSLayoutConstraint *constraint in self.testView.superview.constraints) {
if (constraint.firstItem == self.testView
&& constraint.firstAttribute == NSLayoutAttributeTop) { constraint.constant = constant; } }
改变constant的值(当然也可以去掉重新加)
事实上通过修改而不是删除旧的constraint再添加新的constraint也正是苹果所推荐的,在NSLayoutConstraint.h头文件中有如下说明:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
float move_x = point.x - self.testView.center.x;
float move_y = point.y - self.testView.center.y;
[UIView animateWithDuration:0.5 animations:^{
self.leadingConstraint.constant += move_x ;
self.topConstraint.constant += move_y;
// 这句话注释掉这个 动画写了和没写一样
[self.view layoutIfNeeded];
}];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
NSLog(@"33:%@", NSStringFromCGPoint(point));
float move_x = point.x - self.testView.center.x;
float move_y = point.y - self.testView.center.y;
[UIView animateWithDuration:0.5 animations:^{
self.leadingConstraint.constant += move_x ;
self.topConstraint.constant += move_y;
[self.view layoutIfNeeded];
}];
}
translatesAutoresizingMaskIntoConstraints
= YES 把以前使用的AutoresizingMask转化成constraint
Instead of view transforms, use layer transforms, which do not trigger layout and thus do not cause immediate conflict with constraints.
For example, this simple "throb" view animation may well break under autolayout:
[UIView animateWithDuration:0.3 delay:0
options:UIViewAnimationOptionAutoreverse
animations:^{
v.transform = CGAffineTransformMakeScale(1.1, 1.1);
} completion:^(BOOL finished) {
v.transform = CGAffineTransformIdentity;
}];
Even though in the end there was no change in the view's size, merely setting its transform
causes layout to happen, and constraints can make the view jump around. (Does this feel like a bug or what?) But if we do the same thing with Core Animation (using a CABasicAnimation and applying the animation to the view's layer), layout doesn't happen, and it works fine:
CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:@"transform"];
ba.autoreverses = YES;
ba.duration = 0.3;
ba.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1, 1.1, 1)];
[v.layer addAnimation:ba forKey:nil];