【问题标题】:Objective-C: animating height constraint change not workingObjective-C:动画高度约束更改不起作用
【发布时间】:2018-01-04 08:49:33
【问题描述】:

我有两个代码块,一个有效,第二个无效。首先添加一个视图,将其高度限制为 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 是一个强大的属性,当我第二次激活时它不是 nil。

有什么建议吗?谢谢!

【问题讨论】:

  • mandatoryPickupViewHeight 是强属性吗?
  • 是的,第二次激活时不为零
  • 别叫这个[weakSelf.view layoutIfNeeded];你可以像weakSelf.mandatoryPickupViewHeight.constant = 0一样调整大小
  • 常量已经设置为0,我只是想重新激活常量。你必须调用 layoutIfNeeded
  • @MilanNosáľ 我做到了,这是使用遮罩层来圆角。在回答问题之前,我仍在试图弄清楚为什么会发生这种情况。感谢您的帮助

标签: ios animation constraints autolayout


【解决方案1】:

当你对动画使用自动布局时,你可以这样做:

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

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

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

    self.view.setNeedsLayout()
    
  4. 然后您只需调用 layoutIfNeeded() 即可添加一个动画块:

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

请注意,您没有停用约束 - 它必须始终处于活动状态。

我猜你的代码中的问题就在这里:

    [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 约束与那些没有冲突吗?

【讨论】:

    【解决方案2】:

    这是一种将视图缩小到零高度并使其与子视图一样高的方法。

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

    【讨论】:

    • 奇怪,它第一次工作。重点是我希望通过内部约束来计算高度
    • 也忘记活动/非活动方法
    猜你喜欢
    • 2020-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-14
    相关资源
    最近更新 更多