我正在更新一个带有AdBannerView的旧应用程序,当没有广告时,它就会滑出屏幕。当有广告时,它就会在屏幕上滑动。基本的东西。

旧的风格,我设置帧在一个动画块。 新样式,我有一个IBOutlet到自动布局约束,它决定了Y的位置,在这种情况下,它是从父视图底部的距离,并修改常数:

- (void)moveBannerOffScreen {
    [UIView animateWithDuration:5 animations:^{
        _addBannerDistanceFromBottomConstraint.constant = -32;
    }];
    bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen {
    [UIView animateWithDuration:5 animations:^{
        _addBannerDistanceFromBottomConstraint.constant = 0;
    }];
    bannerIsVisible = TRUE;
}

横幅的移动和预期的完全一样,但是没有动画。


更新:我重新看了WWDC 12演讲《掌握自动布局的最佳实践》,其中包括动画。它讨论了如何使用CoreAnimation更新约束:

我尝试了下面的代码,但得到完全相同的结果:

- (void)moveBannerOffScreen {
    _addBannerDistanceFromBottomConstraint.constant = -32;
    [UIView animateWithDuration:2 animations:^{
        [self.view setNeedsLayout];
    }];
    bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen {
    _addBannerDistanceFromBottomConstraint.constant = 0;
    [UIView animateWithDuration:2 animations:^{
        [self.view setNeedsLayout];
    }];
    bannerIsVisible = TRUE;
}

另一方面,我已经检查了很多次,这是在主线程上执行的。


当前回答

两个重要注意事项:

You need to call layoutIfNeeded within the animation block. Apple actually recommends you call it once before the animation block to ensure that all pending layout operations have been completed You need to call it specifically on the parent view (e.g. self.view), not the child view that has the constraints attached to it. Doing so will update all constrained views, including animating other views that might be constrained to the view that you changed the constraint of (e.g. View B is attached to the bottom of View A and you just changed View A's top offset and you want View B to animate with it)

试试这个:

objective - c

- (void)moveBannerOffScreen {
    [self.view layoutIfNeeded];

    [UIView animateWithDuration:5
        animations:^{
            self._addBannerDistanceFromBottomConstraint.constant = -32;
            [self.view layoutIfNeeded]; // Called on parent view
        }];
    bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen { 
    [self.view layoutIfNeeded];

    [UIView animateWithDuration:5
        animations:^{
            self._addBannerDistanceFromBottomConstraint.constant = 0;
            [self.view layoutIfNeeded]; // Called on parent view
        }];
    bannerIsVisible = TRUE;
}

斯威夫特3

UIView.animate(withDuration: 5) {
    self._addBannerDistanceFromBottomConstraint.constant = 0
    self.view.layoutIfNeeded()
}

其他回答

使用Xcode 8.3.3测试Swift 3的解决方案:

self.view.layoutIfNeeded()
self.calendarViewHeight.constant = 56.0

UIView.animate(withDuration: 0.5, delay: 0.0, options: UIViewAnimationOptions.curveEaseIn, animations: {
        self.view.layoutIfNeeded()
    }, completion: nil)

只要记住那个自我。calendarViewHeight是一个引用自customView (CalendarView)的约束。我在self上调用了. layoutifneeded()。view和NOT在self。calendarview上

希望这对你有所帮助。

迅速的解决方案:

yourConstraint.constant = 50
UIView.animate(withDuration: 1.0, animations: {
    yourView.layoutIfNeeded
})

有一篇文章谈到了这一点: http://weblog.invasivecode.com/post/42362079291/auto-layout-and-core-animation-auto-layout-was

在信中,他是这样写的:

- (void)handleTapFrom:(UIGestureRecognizer *)gesture {
    if (_isVisible) {
        _isVisible = NO;
        self.topConstraint.constant = -44.;    // 1
        [self.navbar setNeedsUpdateConstraints];  // 2
        [UIView animateWithDuration:.3 animations:^{
            [self.navbar layoutIfNeeded]; // 3
        }];
    } else {
        _isVisible = YES;
        self.topConstraint.constant = 0.;
        [self.navbar setNeedsUpdateConstraints];
        [UIView animateWithDuration:.3 animations:^{
            [self.navbar layoutIfNeeded];
        }];
    }
}

希望能有所帮助。

// Step 1, update your constraint
self.myOutletToConstraint.constant = 50; // New height (for example)

// Step 2, trigger animation
[UIView animateWithDuration:2.0 animations:^{

    // Step 3, call layoutIfNeeded on your animated view's parent
    [self.view layoutIfNeeded];
}];

通常,你只需要更新约束并在动画块中调用layoutIfNeeded。这可以是改变NSLayoutConstraint的.constant属性,添加remove约束(iOS 7),或者改变约束的.active属性(iOS 8和9)。

示例代码:

[UIView animateWithDuration:0.3 animations:^{
    // Move to right
    self.leadingConstraint.active = false;
    self.trailingConstraint.active = true;

    // Move to bottom
    self.topConstraint.active = false;
    self.bottomConstraint.active = true;

    // Make the animation happen
    [self.view setNeedsLayout];
    [self.view layoutIfNeeded];
}];

示例设置:

争议

有一些关于约束是否应该在动画块之前或里面改变的问题(见以前的答案)。

以下是教授iOS的马丁·皮尔金顿(Martin Pilkington)和自动布局(Auto Layout)作者肯·费里(Ken Ferry)在Twitter上的对话。Ken解释说,虽然在动画块之外改变常量目前可能工作,但这是不安全的,它们应该在动画块内部改变。 https://twitter.com/kongtomorrow/status/440627401018466305

动画:

示例项目

下面是一个简单的项目,展示了视图如何被动画化。它使用Objective C并通过改变几个约束的.active属性来动画视图。 https://github.com/shepting/SampleAutoLayoutAnimation