Objective-C: animating height constraint change not working

随声附和 提交于 2019-12-11 11:38:44

问题


I have two blocks of code, one working and the second not really. The first adds a view, constraints its height to 0 and then cancel this constraint in an animation block so it grows up. Works perfect. The second one is supposed to reactivate the 0 height constraint so that its height shrinks back to 0 and then remove it, but instead it is removed instantaneously. Here's the code:

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. It's all happening on the main thread.
  2. I tried settings the frame's height to 0 instead, also didn't work
  3. weakSelf.mandatoryPickupViewHeight is a strong property and it is not nil when I activated the second time.

Any suggestions? Thanks!


回答1:


When you are using autolayout for animations, you do it as follows:

  1. Make sure autolayout is done:

    self.view.layoutIfNeeded()
    
  2. Then you change the constraints BEFORE the animation block. So for example:

    someConstraint.constant = 0
    
  3. Then after changing the constraint, you tell the autolayout that constraints have been changed:

    self.view.setNeedsLayout()
    
  4. And then you add an animation block with simply calling layoutIfNeeded():

    UIView.animate(withDuration: 1, animations: {
        self.view.layoutIfNeeded()
    })
    

Notice that you don't deactivate the constraint - it has to be active the whole time.

I guess that in your code the problem is here:

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

Try changing it to

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

Although what you are doing seems a bit obscure. If the constraint is deactivated, are you sure the autolayout has enough constraints to calculate the proper height? If so, are you sure that mandatoryPickupViewHeight constraint is not in collision with those?




回答2:


This is the methodology to shrink a view to zero height and to make it grows as height as of it's subviews.

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


            } ];





}
}


来源:https://stackoverflow.com/questions/48091661/objective-c-animating-height-constraint-change-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!