【问题标题】:Prevent unwanted animations on subviews when animating constraints在为约束设置动画时防止子视图上出现不需要的动画
【发布时间】:2015-03-09 22:31:29
【问题描述】:

在为 UITableView 的高度设置动画时,通常会在 UITableViewCells 上获得不需要的动画。被重用的新单元格进来,并且在布局的子视图上有奇怪的不需要的动画。这通常在表格展开时可见。

动画通常看起来像是从角落弹出的对象,因为它出于某种原因将子视图的宽度和高度从 0 设置为它们应该的大小。

这可以通过覆盖单元格的 layoutSubviews 方法来解决。

- (void)layoutSubviews
{
    [UIView performWithoutAnimation:^{
        [super layoutSubviews];
    }];
}

但这仍然不能阻止包含的子视图执行不需要的动画。当您将内容添加到单元格的 contentView 时,它也不会阻止不需要的动画。如果它也有子视图,你基本上必须覆盖你拥有的每个子视图的 layoutSubviews 方法。

这并不总是可行的,例如 contentView。我不能覆盖 contentView 类并告诉它在没有动画的情况下布置其子视图。这也是一个非常麻烦的修复,因为我需要将它添加到我能够覆盖的每个 UIView 对象中。

我仍然没有找到一劳永逸地解决这个问题的答案。如何仅对某事物的约束设置动画,但防止在其子视图上出现奇怪的不需要的动画。

【问题讨论】:

    标签: ios animation constraints


    【解决方案1】:

    我在 UICollectionView 中遇到了类似的问题,并且能够在其委托中修复它:

    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        // setup your cell
        // ...
    
        [UIView performWithoutAnimation:^{
            [cell layoutIfNeeded];
        }];
    
        return cell;
    }
    

    【讨论】:

    • 这确实有帮助。
    • 效果很好。但如果单元格包含辅助复选标记,复选标记将从左侧动画显示。我试图将此代码sn-p mv 到-tableView:willDisplayCell:forRowAtIndexPath:,解决了我的情况。希望对其他人有所帮助。
    【解决方案2】:

    其他回答是正确的,但您必须在所有视图层次结构上都这样做。添加这个扩展方法,在不需要动画的**子视图**上调用。

    public func commitSuperviewsLayout() {
        var processedSuperview = superview
    
        while processedSuperview != nil {
            processedSuperview?.layoutIfNeeded()
            processedSuperview = processedSuperview?.superview
        }
    }
    

    【讨论】:

      【解决方案3】:

      奇怪的是,如果你把UIView.performWithoutAnimation 放在UIView.animate 之前,它就不起作用。如果你把它放在后面,它会起作用!顺序很重要:D

      func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
          //        print("I am being edited")
          
          if self.searchCancelButton.isHidden {
              UIView.animate(withDuration: 0.2) {
                  self.searchCancelButton.isHidden.toggle()
                  self.topStack.layoutIfNeeded()
              }
          }
          
          UIView.performWithoutAnimation {
              self.state = .searchFoodView
              refreshEmptySearchFoodView()
          }
      }
      

      【讨论】:

        【解决方案4】:

        一般来说,如果我只想为某些东西设置动画而不是其他的,我会确保设置所有不应设置动画的约束,然后调用

        [view layoutIfNeeded]
        

        在受这些约束影响的视图的父视图上。

        最后我在我想要动画和调用的约束上设置了常量

        [UIView animateWithDuration:0.2 animations:^{ [view layoutIfNeeded];}];
        

        【讨论】:

        • 但有时我只需要改变一个tableView的高度。我正在设置一个约束。其余的动画超出了我的控制范围。
        • @iseletsky 指的是系统在您展开视图并且最初具有 0 高度或 0 宽度时所做的动画,它不仅会为您正在展开的一侧设置动画,它还会为另一侧的变化设置动画,或者如果您实例化一个笔尖,它会为从原始大小到新大小的重新调整设置动画。
        猜你喜欢
        • 2013-12-04
        • 2017-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-13
        • 2019-02-21
        • 1970-01-01
        相关资源
        最近更新 更多