iOS 10-11 上的 NSLayoutConstraint 动画问题
NSLayoutConstraint animation issue on iOS 10-11
我正在尝试为视图实现 show/hide 动画。
这个想法是调整视图的高度约束并让它的父视图随之调整大小。为此,我添加了视图的高度约束并将其底部约束固定到超级视图的底部(因此我不需要指定超级视图的高度约束)
在 iOS 9 上按预期工作:
这发生在 iOS 10-11:
动画代码:
#import "ViewController.h"
@interface ViewController ()
{
BOOL _hideFlag;
CGFloat _redViewHeight;
}
@property (strong, nonatomic) IBOutlet UIView *containerView;
@property (strong, nonatomic) IBOutlet UIButton *toggleButton;
@property (strong, nonatomic) IBOutlet UIView *redView;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *redViewHeightConstraint;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[_toggleButton addTarget:self action:@selector(toggle:) forControlEvents:UIControlEventTouchUpInside];
_redViewHeight = _redViewHeightConstraint.constant;
}
- (void)toggle:(UIButton *)sender
{
_hideFlag = !_hideFlag;
[_containerView layoutIfNeeded];
[UIView animateWithDuration:0.2 animations:^{
_redViewHeightConstraint.constant = _hideFlag ? 0 : _redViewHeight;
[_containerView layoutIfNeeded];
}];
}
@end
编辑
感谢@Kuldeep 解决了。只是强调一下:重点是至少在层次结构中受影响的上层视图的超视图上调用 layoutIfNeeded
。所以在我的例子中,由于 containerView
的高度也在变化,我不得不在 containerView
的超级视图上调用 layoutIfNeeded
。
试试这个它在 iOS 9,10,11
中有效
Objective C
- (IBAction)btnChangeTapped:(UIButton *)sender {
sender.selected =! sender.selected;
if (sender.selected) {
[self.view layoutIfNeeded];
[UIView animateWithDuration:1.0 animations:^{
self.constraintHeightOfView.constant = 100.0; // as per your require
[self.view layoutIfNeeded];
}];
}
else {
[self.view layoutIfNeeded];
[UIView animateWithDuration:1.0 animations:^{
self.constraintHeightOfView.constant = 350.0; // Back to Normal
[self.view layoutIfNeeded];
}];
}
}
Swift 5.0
@IBAction func btnChangeTapped(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
self.view.layoutIfNeeded()
UIView.animate(withDuration: 1.0, animations: {
self.constraintHeightOfView.constant = 100.0 // as per your require
self.view.layoutIfNeeded()
})
} else {
self.view.layoutIfNeeded()
UIView.animate(withDuration: 1.0, animations: {
self.constraintHeightOfView.constant = 350.0 // Back to Normal
self.view.layoutIfNeeded()
})
}
}
我正在尝试为视图实现 show/hide 动画。 这个想法是调整视图的高度约束并让它的父视图随之调整大小。为此,我添加了视图的高度约束并将其底部约束固定到超级视图的底部(因此我不需要指定超级视图的高度约束)
在 iOS 9 上按预期工作:
这发生在 iOS 10-11:
动画代码:
#import "ViewController.h"
@interface ViewController ()
{
BOOL _hideFlag;
CGFloat _redViewHeight;
}
@property (strong, nonatomic) IBOutlet UIView *containerView;
@property (strong, nonatomic) IBOutlet UIButton *toggleButton;
@property (strong, nonatomic) IBOutlet UIView *redView;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *redViewHeightConstraint;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[_toggleButton addTarget:self action:@selector(toggle:) forControlEvents:UIControlEventTouchUpInside];
_redViewHeight = _redViewHeightConstraint.constant;
}
- (void)toggle:(UIButton *)sender
{
_hideFlag = !_hideFlag;
[_containerView layoutIfNeeded];
[UIView animateWithDuration:0.2 animations:^{
_redViewHeightConstraint.constant = _hideFlag ? 0 : _redViewHeight;
[_containerView layoutIfNeeded];
}];
}
@end
编辑
感谢@Kuldeep 解决了。只是强调一下:重点是至少在层次结构中受影响的上层视图的超视图上调用 layoutIfNeeded
。所以在我的例子中,由于 containerView
的高度也在变化,我不得不在 containerView
的超级视图上调用 layoutIfNeeded
。
试试这个它在 iOS 9,10,11
中有效Objective C
- (IBAction)btnChangeTapped:(UIButton *)sender {
sender.selected =! sender.selected;
if (sender.selected) {
[self.view layoutIfNeeded];
[UIView animateWithDuration:1.0 animations:^{
self.constraintHeightOfView.constant = 100.0; // as per your require
[self.view layoutIfNeeded];
}];
}
else {
[self.view layoutIfNeeded];
[UIView animateWithDuration:1.0 animations:^{
self.constraintHeightOfView.constant = 350.0; // Back to Normal
[self.view layoutIfNeeded];
}];
}
}
Swift 5.0
@IBAction func btnChangeTapped(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
self.view.layoutIfNeeded()
UIView.animate(withDuration: 1.0, animations: {
self.constraintHeightOfView.constant = 100.0 // as per your require
self.view.layoutIfNeeded()
})
} else {
self.view.layoutIfNeeded()
UIView.animate(withDuration: 1.0, animations: {
self.constraintHeightOfView.constant = 350.0 // Back to Normal
self.view.layoutIfNeeded()
})
}
}