我想滚动到UITableView中靠近某个单元格的位置。
我用这个代码:

myTableView.scrollToRow(at: index,at: .top, animated: true)

动画完成后我会:
myTableView.setContentOffset(CGPoint(x: 0, y: myTableView.contentOffset.y + myCloseToCellOffset), animated: true)

但问题是动画被分成两个动画,因此运行不顺畅。有没有办法把这个变成一个动画?或者用其他方法得到我想要的结果?

最佳答案

在我看来,只有当两个卷轴的方向相同时,这两个动画之间令人不快的停顿才是令人不快的。当它不同的时候(先上,然后下),我觉得很好。所以我建议如下(也许有一个更简单的解决方案,但这正是我所想的):
计算您自己通过myTableView.scrollToRow(at: index,at: .top, animated: true)获得的偏移量。
如果偏移量的变化方向与添加myCloseToCellOffset时的变化方向相同,只需添加myCloseToCellOffset并直接调用myTableView.setContentOffset(CGPoint(x: 0, y: myTableView.contentOffset.y + (initalOffset + myCloseToCellOffset), animated: true)
如果偏移量的变化方向不同于通过myCloseToCellOffset实现的偏移量变化,则进行两次调用。首先myTableView.setContentOffset(CGPoint(x: 0, y: myTableView.contentOffset.y + initalOffset, animated: true)然后'myTableView.setContentOffset(CGPoint(x:0,y:myTableView.contentOffset.y+myCloseToCellOffset,动画:true)
我不知道myCloseToCellOffset是什么,所以我想它可能是正的,也可能是负的,也可能是零。
下面是一些实现示例,我希望没有错误,希望足够详细:

enum TableViewChangeDirections {
case upUp
case downDown
case upDown
case downUp
case unimportant
}

extension Double {
/// Rounds the double to decimal places value
    func rounded(toPlaces places:Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self * divisor).rounded() / divisor
    }
}

然后在视图控制器中保存表视图
let numberOfCells = 20
let cellToMakeVisibleIndex = 5
let heightOfCell : CGFloat = 44
let myCloseToCellOffset : CGFloat = 100

var firstDesiredYOffset: CGFloat!
var secondDesiredYOffset: CGFloat!

这将找到scrollToRow的偏移量
func tableViewOffset(forCellToGoTo cellToGoTo: CGFloat) -> CGFloat {
    let desiredOffset = heightOfCell * cellToGoTo
    var maxContentOffset = CGFloat(numberOfCells)*heightOfCell - tableView.frame.size.height
    maxContentOffset = (maxContentOffset >= 0) ? maxContentOffset : 0
    return (desiredOffset > maxContentOffset) ? maxContentOffset : desiredOffset
}

如果方向相反,这将执行第二个偏移更改:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if (tableView.isUserInteractionEnabled == false && self.secondDesiredYOffset != nil && self.firstDesiredYOffset != nil && Double(tableView.contentOffset.y).rounded(toPlaces: 2) == Double(self.firstDesiredYOffset).rounded(toPlaces: 2)) {
        self.tableView.setContentOffset(CGPoint(x: 0, y: self.secondDesiredYOffset), animated: true)
        self.secondDesiredYOffset = nil
        self.tableView.isUserInteractionEnabled = true
    }
}

这将返回两个偏移更改的方向:
    var changeDirections : TableViewChangeDirections {
    if self.firstDesiredYOffset > self.tableView.contentOffset.y && myCloseToCellOffset >= 0 {
        return .upUp
    } else if self.firstDesiredYOffset > self.tableView.contentOffset.y && myCloseToCellOffset < 0 {
        return .upDown
    } else if self.firstDesiredYOffset < self.tableView.contentOffset.y && myCloseToCellOffset <= 0 {
        return .downDown
    } else if self.firstDesiredYOffset < self.tableView.contentOffset.y && myCloseToCellOffset > 0 {
        return .downUp
    } else {
        return .unimportant
    }
}

最后更改一般偏移的位置。我把它放在按钮上,但你把它放在你需要的地方:
 @IBAction func didPressButton(_ sender: Any) {

    self.firstDesiredYOffset = self.tableViewOffset(forCellToGoTo: CGFloat(cellToMakeVisibleIndex))
    self.tableView.setContentOffset(CGPoint(x: 0, y: self.firstDesiredYOffset), animated: true)

    switch (self.changeDirections) {
    case .upUp, .downDown:
        self.firstDesiredYOffset = self.firstDesiredYOffset + myCloseToCellOffset
        self.tableView.setContentOffset(CGPoint(x: 0, y: self.firstDesiredYOffset), animated: true)
    case .upDown, .downUp:
        self.tableView.isUserInteractionEnabled = false
        self.secondDesiredYOffset = self.firstDesiredYOffset + myCloseToCellOffset
        self.tableView.setContentOffset(CGPoint(x: 0, y: self.firstDesiredYOffset), animated: true)
    case .unimportant:
        self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.contentOffset.y + myCloseToCellOffset), animated: true)
    }

}

08-15 20:05