约束不像我预期的那样有效

时间:2014-11-17 05:12:05

标签: ios swift autolayout nslayoutconstraint

我有两个这样的观点:

enter image description here

我设置了垂直空间约束:

enter image description here

如您所见,BottomView顶部和TopView底部之间的约束为0.但遗憾的是,当我点击切换按钮移动时,它不正确顶视图。这是代码:

@IBAction func onToggle(sender: AnyObject) {

    self.topView.transform = CGAffineTransformMakeTranslation(0, -self.topView.bounds.height)
}

即使我添加:

,它也是一样的
    self.view.setNeedsUpdateConstraints()
    self.view.setNeedsLayout()

结果是:

enter image description here

显然,TopView的底部和BottomView顶部之间的边距不是0.自动布局不起作用。我错过了什么吗?感谢

P.S。:我知道还有另一种方法可以解决这个问题。例如,在按下切换按钮时更改BottomView的框架。但我的问题是为什么自动布局不像我期望的那样工作?

3 个答案:

答案 0 :(得分:1)

似乎iOS 8有一个调整UILabel高度约束的错误。

无论如何,假设您的两个视图不是UILabel,我建议使用的方法是创建一个属性来记住顶视图的高度约束:

@interface ViewController : UIViewController

@property (nonatomic, strong) UIView *topView;
@property (nonatomic, strong) UIView *bottomView;

// -----------------------------------------------------------
// We will animate this NSLayoutConstraint's constant value
// -----------------------------------------------------------
@property (nonatomic, strong) NSLayoutConstraint *topViewHeightConstraint;

@end

然后设置我们的视图和切换按钮:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [self initViews];
    [self initConstraints];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)initViews
{
    self.edgesForExtendedLayout = UIRectEdgeNone;
    self.navigationController.navigationBar.translucent = NO;

    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Toggle" style:UIBarButtonItemStylePlain target:self action:@selector(toggleTopView)];

    self.topView = [[UIView alloc] init];
    self.topView.backgroundColor = [UIColor colorWithRed:203.0/255.0 green:89.0/255.0 blue:91.0/255.0 alpha:1.0];

    self.bottomView = [[UIView alloc] init];
    self.bottomView.backgroundColor = [UIColor colorWithRed:103.0/255.0 green:167.0/255.0 blue:187.0/255.0 alpha:1.0];

    [self.view addSubview:self.topView];
    [self.view addSubview:self.bottomView];
}

-(void)initConstraints
{
    self.topView.translatesAutoresizingMaskIntoConstraints = NO;
    self.bottomView.translatesAutoresizingMaskIntoConstraints = NO;

    self.topView.layoutMargins = UIEdgeInsetsZero;
    self.bottomView.layoutMargins = UIEdgeInsetsZero;

    id views = @{
                 @"topView": self.topView,
                 @"bottomView": self.bottomView
                 };

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[topView]|" options:0 metrics:nil views:views]];

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[bottomView]|" options:0 metrics:nil views:views]];


    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topView][bottomView]|" options:0 metrics:nil views:views]];

    self.topViewHeightConstraint = [NSLayoutConstraint constraintWithItem:self.topView
                                                                attribute:NSLayoutAttributeHeight
                                                                relatedBy:NSLayoutRelationEqual toItem:nil
                                                                attribute:NSLayoutAttributeHeight
                                                               multiplier:1.0 constant:170.0];

    [self.view addConstraint:self.topViewHeightConstraint];
}

-(void)toggleTopView
{
    if(self.topViewHeightConstraint.constant != 0)
    {
        self.topViewHeightConstraint.constant = 0;
    }
    else
    {
        self.topViewHeightConstraint.constant = 170.0;
    }

    [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^{

        [self.view layoutIfNeeded];

    } completion:nil];


}

你最初得到这个:

screenshot 1

然后当你点击切换按钮时,我们将heightConstraint属性常量设置为0:

-(void)toggleTopView
{
    if(self.topViewHeightConstraint.constant != 0)
    {
        self.topViewHeightConstraint.constant = 0;
    }
    else
    {
        self.topViewHeightConstraint.constant = 170.0;
    }

    [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^{

        [self.view layoutIfNeeded];

    } completion:nil];
}

你得到了红色的平滑折叠动画:

screenshot 2

答案 1 :(得分:1)

我认为它可能与TopView的约束有关。将translate转换应用于顶视图时,TopView的框架已更改。因此它的最高边际约束也发生了变化。这将影响底部视图的上边距约束。

我的建议是不要为UIView应用翻译变换。而是更改顶视图的顶部垂直空间约束。

    self.topConstraint.constant = -self.topView.bounds.height

底部视图将以这种方式跟随顶视图。这意味着自动布局确实有效。希望它会有所帮助。

答案 2 :(得分:0)

在完成其余布局代码后,将应用视图上的转换。这包括自动布局,因此如果您更改视图的变换,它将不会影响自动布局。转换将相对于自动布局放置视图的位置。