AutoLayout---动画

参考

如何对使用了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来实现。

下面看一些简单的情况

一.移动位置

创建一个简单的view 随着点击或拖动到处移动
AutoLayout---动画_第1张图片

把view的top 和 leading 的属性拖出来

AutoLayout---动画_第2张图片
如果你不想拖出来也可以用代码找的

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];
    }];
}

二 旋转 放大

如果像下图这么限制的话
AutoLayout---动画_第3张图片

在ios8 下AutoLayout和旋转放大并没什么冲突  正是我要的以view.center为中心进行旋转放大,限制对这个view的放大并没有影响
但是在ios7 view就不会以view.center为中心进行旋转放大,会跑到别的地方去


如果把限制改成这样的话就一切正常 ios7,8的旋转放大都没用问题
AutoLayout---动画_第4张图片

在http://stackoverflow.com/questions/12943107/how-do-i-adjust-the-anchor-point-of-a-calayer-when-auto-layout-is-being-used/14105757#14105757
还提供了一些解决方法

Solution 1: No Constraints

这种方法是去除所有的手动限制, translatesAutoresizingMaskIntoConstraints  = YES 把以前使用的AutoresizingMask转化成constraint
我试过了OK

Solution 2: Use Only Appropriate Constraints

利用合适的限制 一般都是设置中心点和大小

Solution 3: Use a Subview

但是按上面的方法那么做的话就失去了Autolayout的优势。 我们可以设置一个看不到的白色的HostView(限制可以随意限制)作为淡红色的otherView可以移动的区域
AutoLayout---动画_第5张图片

淡红色的otherView的中心和hostView的中心对齐

Solution 4: Use Layer Transforms Instead

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];

你可能感兴趣的:(iOS开发系列)