在UITableView中使用动画在顶部插入行

时间:2016-07-21 03:11:05

标签: ios swift uitableview row insertion

我有自定义UITableViewCell的标准UITableView。我想要实现的是:

  • 每一行都会在出现在TableView上时逐渐淡入。

  • 但是,需要注意的是,每个新行应始终插入顶部,从而将先前存在的行按下1个单元格 - 以获得“推送到堆栈”动画。

这是我到现在为止所做的事情,其中​​包含香草的单个插入淡入但在底部:

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
  cell.alpha = 0
  let delayBetweenRowInserts = 0.5 + Double(indexPath.row) * 1.0; //calculate delay
  UIView.animateWithDuration(1, delay: delayBetweenRowInserts, options: .TransitionCurlUp, animations: {
     cell.alpha = 1.0
     }, completion: nil
  )
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  if let cell = leaderboardTableView.dequeueReusableCellWithIdentifier(CUSTOM_CELL) as? CustomTableViewCell {
      let playerName = Array(Games.leaderboard[indexPath.row].keys)[0]
      let playerScore = Array(Games.leaderboard[indexPath.row].values)[0]
      cell.configureCell(playerName, score: "\(playerScore)")
      return cell
   } else {
       return UITableViewCell()
   }   
}

动机:我基本上必须一次性耗尽我的dataSource数组中的所有数据,即Games.leaderboard,而不依赖于用户向下滚动以防他的屏幕尺寸太小而不适合一切。这构成了我的应用程序用户体验中非常重要的一部分。

非常感谢任何帮助!谢谢

P.S作为替代方案,我尝试使用.Uop的beginUpdates(): 我尝试过使用beginUpdates()。在我看来它不会改变动画行的索引。我在dataSource准备就绪后调用startInsertingRows()

func startInsertingRows() {
    var indexPaths = [NSIndexPath]()
    for index in 0...Games.leaderboard.count-1 {
        indexPaths.append(NSIndexPath(forItem: Games.leaderboard.count-1-index, inSection: 0))
    }
    leaderboardTableView.beginUpdates()
    leaderboardTableView.insertRowsAtIndexPaths((indexPaths), withRowAnimation: .Top)
    leaderboardTableView.endUpdates()
}

1 个答案:

答案 0 :(得分:0)

我会通过操纵numberOfRowsInSection和操作此值的NSTimer返回的值来解决此问题。为简单起见,我的版本使用固定的时间间隔,但您可以使用非重复计时器并在tableTick中再次安排。另外,我在viewDidAppear中启动动画,但如果数据尚未加载,则可能不适合您,但您可以根据需要进行调整。

var tableTimer: NSTimer?
var cellPointer = 0

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    cellPointer = Games.leaderboard.count
    self.tableTimer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: #selector(ViewController.tableTick), userInfo: nil, repeats: true)
}

func tableTick() {
    if cellPointer > 0 {
        cellPointer -= 1
        self.tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: 0, inSection: 0)], withRowAnimation: .Fade)
    } else {
        self.tableTimer!.invalidate()
        self.tableTimer = nil
    }
}

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    if let timer = self.tableTimer {
        timer.invalidate()
        self.tableTimer = nil
    }
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return Games.leaderboard.count-self.cellPointer
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    if let cell = leaderboardTableView.dequeueReusableCellWithIdentifier(CUSTOM_CELL) as? CustomTableViewCell {
        let index = cellPointer + indexPath.row
        let playerName = Array(Games.leaderboard[index].keys)[0]
        let playerScore = Array(Games.leaderboard[index].values)[0]
        cell.configureCell(playerName, score: "\(playerScore)")
        return cell
    } else {
        return UITableViewCell()
    }
}