Objective-C:动画高度约束变化不起作用

时间:2018-01-04 08:49:34

标签: ios animation constraints nsautolayout

我有两个代码块,一个工作,第二个不是真的。第一个添加一个视图,将其高度限制为0,然后在动画块中取消此约束,使其长大。工作完美。第二个应该重新激活0 height constraint,使其高度缩回到0,然后将其删除,但它会立即被删除。这是代码:

self.pickupAddressViewModel.infoViewBlock = ^(MandatoryPickupView * _Nonnull pickupView) {
        if (weakSelf.mandatoryPickupView) {
            return;
        }
        weakSelf.mandatoryPickupView = pickupView;
        [weakSelf.view addSubview:pickupView];

        CGFloat gap = weakSelf.orderButton.originY;
        [[pickupView.bottomAnchor constraintEqualToAnchor:weakSelf.view.bottomAnchor constant:-gap] setActive:YES];
        [[pickupView.leadingAnchor constraintEqualToAnchor:weakSelf.view.leadingAnchor
                                                  constant:16.0] setActive:YES];
        [[pickupView.trailingAnchor constraintEqualToAnchor:weakSelf.view.trailingAnchor
                                                   constant:-16.0] setActive:YES];
        weakSelf.mandatoryPickupViewHeight = [pickupView.heightAnchor constraintEqualToConstant:0];
        [weakSelf.mandatoryPickupViewHeight setActive:YES];

        [weakSelf.view layoutIfNeeded];
        [UIView animateWithDuration:0.5 animations:^{
            [weakSelf.mandatoryPickupViewHeight setActive:NO];
            [weakSelf.view layoutIfNeeded];
        }];
    };
    self.pickupAddressViewModel.closeViewBlock = ^{
        if (!weakSelf.mandatoryPickupView) {
            return;
        }
        [weakSelf.view layoutIfNeeded];
        [UIView animateWithDuration:10.5
                         animations:^{
                             [weakSelf.mandatoryPickupViewHeight setActive:YES];
                             [weakSelf.view layoutIfNeeded];
                         } completion:^(BOOL finished) {
                             [weakSelf.mandatoryPickupView removeFromSuperview];
                             weakSelf.mandatoryPickupView = nil;
                             weakSelf.mandatoryPickupViewHeight = nil;
                         }];
    };
  1. 这一切都发生在主线上。
  2. 我尝试将框架的高度设置为0,而不是
  3. weakSelf.mandatoryPickupViewHeight是一个强大的属性,当我第二次激活时它不是零。
  4. 有什么建议吗?谢谢!

2 个答案:

答案 0 :(得分:1)

当您使用autolayout制作动画时,请按以下步骤操作:

  1. 确保自动布局已完成:

    self.view.layoutIfNeeded()
    
  2. 然后在动画块之前更改约束。例如:

    someConstraint.constant = 0
    
  3. 然后在更改约束后,告诉自动布局已更改约束:

    self.view.setNeedsLayout()
    
  4. 然后添加动画块,只需调用layoutIfNeeded()

    UIView.animate(withDuration: 1, animations: {
        self.view.layoutIfNeeded()
    })
    
  5. 请注意,您不会停用约束 - 它必须始终处于活动状态。

    我想你的代码中存在问题:

        [UIView animateWithDuration:0.5 animations:^{
            [weakSelf.mandatoryPickupViewHeight setActive:NO];
            [weakSelf.view layoutIfNeeded];
        }];
    

    尝试将其更改为

        [weakSelf.mandatoryPickupViewHeight setActive:NO];
        [weakSelf.view setNeedsLayout];
        [UIView animateWithDuration:0.5 animations:^{
            [weakSelf.view layoutIfNeeded];
        }];
    

    虽然你在做什么似乎有点模糊。如果禁用约束,您确定自动布局有足够的约束来计算适当的高度吗?如果是这样,您确定mandatoryPickupViewHeight约束与那些没有碰撞吗?

答案 1 :(得分:0)

这是将视图缩小到零高度并使其增长为其子视图的高度的方法。

 -(void)manageViewCollapse
 {

    if(animationRunning)
   {
      return ;
   }

    animationRunning = YES;

  if(supportShown)
  {

      // Hide the view by setting its height constant to zero
      NSLayoutConstraint*full=[NSLayoutConstraint constraintWithItem:self.supportView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:0.0];


    [self.supportView addConstraint:full];

    // retrieve the bottom constraint of the view with bottom most item and remove it
    for (NSLayoutConstraint*con in self.supportView.constraints)
    {
        if (con.firstAttribute == NSLayoutAttributeBottom && con.firstItem == self.bottomItemView)
        {

            [self.supportView removeConstraint:con];

            break;
        }


    }

        [UIView animateWithDuration:0.5 animations:^{
            [self.view layoutIfNeeded];

            }completion:^(BOOL finished){

            supportShown = NO;
            animationRunning = NO ;



            } ];


}
else
{
    // show the view first by deleting it's zero height

    for (NSLayoutConstraint*con in self.supportView.constraints)
    {
        if (con.firstAttribute == NSLayoutAttributeHeight)
        {

            [self.supportView removeConstraint:con];

            break;
        }


    }

   // hook the bottom of the view again to the bottom most item to make it have the correct height

    NSLayoutConstraint*full1=[NSLayoutConstraint constraintWithItem:self.bottomItemView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.supportView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-15.0];

    full1.priority = UILayoutPriorityDefaultHigh;

    [self.supportView addConstraint:full1];


      [UIView animateWithDuration:0.5 animations:^{
            [self.view layoutIfNeeded];

            }completion:^(BOOL finished){

            supportShown = YES;
            animationRunning = NO;


            } ];





}
}