【问题标题】:UITableView row animation duration and completion callbackUITableView 行动画持续时间和完成回调
【发布时间】:2011-04-19 10:47:05
【问题描述】:

有没有办法指定 UITableView 行动画的持续时间,或者在动画完成时获取回调?

我想做的是在动画完成后闪烁滚动指示器。在那之前做闪光灯没有任何作用。到目前为止,我的解决方法是延迟半秒(这似乎是默认的动画持续时间),即:

[self.tableView insertRowsAtIndexPaths:newRows
                      withRowAnimation:UITableViewRowAnimationFade];
[self.tableView performSelector:@selector(flashScrollIndicators)
                     withObject:nil
                     afterDelay:0.5];

【问题讨论】:

  • 我自己没试过,但也许可以通过一些索引路径处理来做到这一点:- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath

标签: ios iphone uitableview animation cocoa-touch


【解决方案1】:

您可以尝试将 insertRowsAtIndexPath 包装在

- (void)beginUpdates
- (void)endUpdates

事务,然后做flash。

【讨论】:

  • 见上面karwag的回答。你需要解决什么算“后来”的问题。
【解决方案2】:

刚刚遇到这个。操作方法如下:

Objective-C

[CATransaction begin];
[tableView beginUpdates];
[CATransaction setCompletionBlock: ^{
    // Code to be executed upon completion
}];
[tableView insertRowsAtIndexPaths: indexPaths
                 withRowAnimation: UITableViewRowAnimationAutomatic];
[tableView endUpdates];
[CATransaction commit];

斯威夫特

CATransaction.begin()
tableView.beginUpdates()
CATransaction.setCompletionBlock {
    // Code to be executed upon completion
}
tableView.insertRowsAtIndexPaths(indexArray, withRowAnimation: .Top)
tableView.endUpdates()
CATransaction.commit()

【讨论】:

  • 再次,在这里完美运行。 iOS6 和所有。这是一种适当的 SDK 支持机制,用于覆盖默认动画中的属性。也许您的 CATransaction 中有额外的、运行时间更长的动画?你知道,它们是嵌套的。
  • 在 iOS6 中非常适合我。谢谢!
  • setAnimationDuration 似乎不会影响插入/删除持续时间。 iOS 6
  • 关于如何更改持续时间的任何建议? CATransaction setAnimationDuration: 似乎没有什么区别。
  • 在 iOS 5.1.1、6.1、7.0 中也适用于我;但是,如果您需要在动画后获得一个新的 tableView.contentSize(就像我的情况一样),您必须使用 [self performSelectorOnMainThread:withObject:waitUntilDone:];在 setCompletionBlock 中,以便在下一个运行循环中调用您的委托。如果您直接调用您的委托,而不使用 performSelectorOnMainThread,您将获得 tableView.contentSize 的旧值。
【解决方案3】:

扩展 karwag's fine answer,注意在 iOS 7 上,使用 UIView 动画围绕 CATransaction 提供对表格动画持续时间的控制。

[UIView beginAnimations:@"myAnimationId" context:nil];

[UIView setAnimationDuration:10.0]; // Set duration here

[CATransaction begin];
[CATransaction setCompletionBlock:^{
    NSLog(@"Complete!");
}];

[myTable beginUpdates];
// my table changes
[myTable endUpdates];

[CATransaction commit];
[UIView commitAnimations];

UIView 动画的持续时间对 iOS 6 没有影响。也许 iOS 7 表格动画的实现方式不同,在 UIView 级别。

【讨论】:

  • 动画持续时间似乎被忽略了。
【解决方案4】:

缩短 Brent's fine answer,至少对于 iOS 7,您可以将这一切简洁地包装在 [UIView animateWithDuration:delay:options:animations:completion:] 调用中:

[UIView animateWithDuration:10 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
  [self.tableView beginUpdates];
  [self.tableView endUpdates];
} completion:^(BOOL finished) {
  // completion code
}];

不过,除了 EaseInOut 之外,我似乎无法覆盖默认动画曲线。

【讨论】:

  • 当以这种方式或@Brent 的方式进行行插入时,虽然持续时间得到尊重,但 UITableViewRowAnimation 似乎没有得到尊重,并且总是出现自上而下的动画,即使我指定了,例如UITableViewRowAnimationLeft。在 iOS 8.4 上进行测试 - 有人有解决方案吗?
【解决方案5】:

对我来说,我需要这个作为 collectionView。我做了一个简单的扩展来解决这个问题:

extension UICollectionView {

    func reloadSections(sections: NSIndexSet, completion: () -> Void){
        CATransaction.begin()
        CATransaction.setCompletionBlock(completion)

        self.reloadSections(sections)

        CATransaction.commit()
    }

}

【讨论】:

    【解决方案6】:

    这是karwag's answer 的 Swift 版本

    CATransaction.begin()
    tableView.beginUpdates()
    CATransaction.setCompletionBlock { () -> Void in
        // your code here
    }
    tableView.insertRowsAtIndexPaths(indexArray, withRowAnimation: .Top)
    tableView.endUpdates()
    CATransaction.commit()
    

    【讨论】:

      【解决方案7】:

      这是一个非常有用的技巧! 我写了一个 UITableView 扩展来避免一直写 CATransaction 的东西。

      import UIKit
      
      extension UITableView {
      
          /// Perform a series of method calls that insert, delete, or select rows and sections of the table view.
          /// This is equivalent to a beginUpdates() / endUpdates() sequence, 
          /// with a completion closure when the animation is finished.
          /// Parameter update: the update operation to perform on the tableView.
          /// Parameter completion: the completion closure to be executed when the animation is completed.
         
          func performUpdate(_ update: ()->Void, completion: (()->Void)?) {
          
              CATransaction.begin()
              CATransaction.setCompletionBlock(completion)
      
              // Table View update on row / section
              beginUpdates()
              update()
              endUpdates()
          
              CATransaction.commit()
          }
      
      }
      

      这样使用:

      // Insert in the tableView the section we just added in sections
      self.tableView.performUpdate({
          self.tableView.insertSections([newSectionIndex], with: UITableViewRowAnimation.top)
      
      }, completion: {
          // Scroll to next section
          let nextSectionIndexPath = IndexPath(row: 0, section: newSectionIndex)
          self.tableView.scrollToRow(at: nextSectionIndexPath, at: .top, animated: true)
      })
      

      【讨论】:

      • 很棒的答案!这是我喜欢 Swift 的原因之一
      • @GianniCarlo 你也可以在 ObjC 中做到这一点
      • @Cyber​​Mew 是的,但是创建类别一直很痛苦,特别是由于额外文件的名称很长
      • 只有ios 11才有,ios 10怎么用?
      • @kemdo 为什么说它只在 iOS 11 中可用?这里的一切都是 iOS 2+ 除了setCompletionBlock 这是 iOS 4+
      【解决方案8】:

      现在如果你想这样做,有新功能starting from iOS 11

      - (void)performBatchUpdates:(void (^)(void))updates 
                       completion:(void (^)(BOOL finished))completion;
      

      在更新闭包中放置与 beginUpdates()/endUpdates 部分相同的代码。并且完成在所有动画之后执行。

      【讨论】:

      • 这很棒。我没有注意到这个添加。
      【解决方案9】:

      由于 tableView 的 performBatch 方法仅从 iOS 11 开始可用,您可以使用以下扩展:

      extension UITableView {
      func performUpdates(_ updates: @escaping () -> Void, completion: @escaping (Bool) -> Void) {
              if #available(iOS 11.0, *) {
                  self.performBatchUpdates({
                      updates()
                  }, completion: completion)
              } else {
                  CATransaction.begin()
                  beginUpdates()
                  CATransaction.setCompletionBlock {
                      completion(true)
                  }
                  updates()
                  endUpdates()
                  CATransaction.commit()
              }
          }
      }
      

      【讨论】:

        【解决方案10】:

        Antoine's answer 非常好——但适用于 UICollectionView。这是 UITableView:

        extension UITableView {
            func reloadSections(_ sections: IndexSet, with rowAnimation: RowAnimation, completion: (() -> Void)?) {
                CATransaction.begin()
                CATransaction.setCompletionBlock(completion)
                
                self.reloadSections(sections, with: rowAnimation)
                
                CATransaction.commit()
            }
        }
        

        这样称呼:

        tableView.reloadSections(IndexSet(0), with: .none, completion: {
            // Do the end of animation thing        
        })
        

        【讨论】:

          【解决方案11】:

          如果有人在 tableView 忽略 UIView.animate 中的动画参数并使用“从上到下”默认动画重新加载行时遇到问题,我找到了一个奇怪的解决方案:

          你需要:

          1. 静音tableView动画
          2. 改用transitionAnimation

          例子:

          let indicesToUpdate = [IndexPath(row: 1, section: 0)]
          UIView.transition(with: self.tableView,
                                duration: 0.5,
                                options: [.transitionCrossDissolve,
                                          .allowUserInteraction,
                                          .beginFromCurrentState],
                                animations: {
                                  UIView.performWithoutAnimation {
                                      self.tableView.reloadRows(at: indicesToUpdate,
                                                                with: .none)
                                  }
                                })
          

          PS:UIView.transition(..) 也有可选的补全:)

          【讨论】:

            猜你喜欢
            • 2019-07-20
            • 1970-01-01
            • 2018-06-15
            • 2014-03-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多