Objective-C:动画高度约束更改不起作用

Posted

技术标签:

【中文标题】Objective-C:动画高度约束更改不起作用【英文标题】:Objective-C: animating height constraint change not working 【发布时间】: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;
                         ];
    ;
    这一切都发生在主线程上。 我尝试将框架的高度设置为 0,但也没有用 weakSelf.mandatoryPickupViewHeight 是一个强大的属性,当我第二次激活时它不是 nil。

有什么建议吗?谢谢!

【问题讨论】:

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

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

    确保自动布局已完成:

    self.view.layoutIfNeeded()
    

    然后您在动画块之前更改约束。比如:

    someConstraint.constant = 0
    

    然后在更改约束后,告诉自动布局约束已更改:

    self.view.setNeedsLayout()
    

    然后您只需调用 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;


             ];







【讨论】:

奇怪,它第一次工作。重点是我希望通过内部约束来计算高度 也忘记活动/非活动方法

以上是关于Objective-C:动画高度约束更改不起作用的主要内容,如果未能解决你的问题,请参考以下文章

通过动画调整 UIView 大小时约束不起作用

图像高度约束不起作用

高度动画不起作用

动画后自动布局约束不起作用[重复]

在约束上动画更改 UITableView 节标题的高度

swift animateWithDuration 在 iOS 7 中不起作用