我想滚动到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)
}
}