我有一个UITableView,它有可能有很多行(导入联系人),我希望实现类似于Snapchat的自定义滚动指示器。两个基本目标如下:
滚动桌面视图时,滚动指示器向下/向上移动正确的数量(并且不超过桌面视图的顶部或底部)。
拖动滚动指示器时,它不仅会跟随您的手指,还会将桌面视图滚动到正确的数量。
我一直在尝试对滚动量使用不同的计算,但我似乎无法让它变得正确。我一直在做一个示例应用程序(只是在tableview中包含名称)的工作,我可以让它在那里工作正常但是当我将代码转移到更大的tableview时,它不能正常工作。
我已经为我的滚动指示器创建了一个自定义视图,它基本上只是一个带有标签的视图,该视图会根据单元格中的名称字母而改变:
class IndicatorView: UIView {
@IBOutlet var contentView: UIView!
@IBOutlet weak var letterLabel: UILabel!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
private func commonInit() {
Bundle.main.loadNibNamed("IndicatorView", owner: self, options: nil)
contentView.translatesAutoresizingMaskIntoConstraints = false
addSubview(contentView)
contentView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
contentView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
contentView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
contentView.layer.cornerRadius = 5
}
}
以下是我使用的方法......
scrollViewWillEndDragging:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
//Get velocity and store in global variable
self.velocity = velocity.y
}
scrollViewDidScroll:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
scrollBar.becomeFirstResponder()
let offset: CGPoint = scrollView.contentOffset
var frame = self.scrollBar.frame
var numberOfRows = 0
for i in 0...friendsTableView.numberOfSections - 1 {
let rows = friendsTableView.numberOfRows(inSection: i)
numberOfRows += rows
}
//Calculate the amount of scroll
let percentage = (44*CGFloat(numberOfRows) + 40)/friendsTableView.frame.height
UIView.animate(withDuration: 0.0) {
//Set the y value to new percentage
frame.origin.y = 30 + offset.y + (offset.y/percentage)
//Set label to correct letter
let currentPoint = CGPoint(x: 30, y: frame.origin.y)
if let indexPath = self.friendsTableView.indexPathForRow(at: currentPoint) {
let letter = self.sectionHeaders[indexPath.section]
self.scrollBar.letterLabel.text = letter
}
//Only expand the scroll indicator if the user scrolls fast enough
if abs(self.velocity) > 1.5 {
self.scrollBar.letterLabel.isHidden = false
frame.size.width = 50
frame.origin.x = self.screenWidth - 50
}
//Set the new y value of the scroll indicator
self.scrollBar.frame = frame
}
}
Custom Pan Gesture Recognizer:
@objc func customDrag(_ sender: UIPanGestureRecognizer) {
self.friendsTableView.bringSubview(toFront: scrollBar)
//Only expand fully if the state is not ended
if sender.state != .ended {
var frame = self.scrollBar.frame
//Expand the view fully
self.scrollBar.letterLabel.isHidden = false
frame.size.width = 100
frame.origin.x = self.screenWidth - 100
self.scrollBar.frame = frame
//Get translation and track the content offset
let translation = sender.translation(in: friendsTableView)
let originalContentOffset = friendsTableView.contentOffset
var numberOfRows = 0
for i in 0...friendsTableView.numberOfSections - 1 {
let rows = friendsTableView.numberOfRows(inSection: i)
numberOfRows += rows
}
//Calculate the percentage of scroll and add the translation to the original content offset
let percentage = (44*CGFloat(numberOfRows) + 50)/friendsTableView.frame.height
let vertTranslation = (percentage*translation.y) + originalContentOffset.y
//Set the content offset and the center of the scroll indicator
friendsTableView.contentOffset = CGPoint(x: 0, y: (vertTranslation))
self.scrollBar.center = CGPoint(x: self.screenWidth-50, y: self.scrollBar.center.y + (translation.y/percentage))
sender.setTranslation(CGPoint.zero, in: friendsTableView)
} else {
//once the state is ended, collapse back to the smaller size
var frame = self.scrollBar.frame
self.scrollBar.letterLabel.isHidden = false
frame.size.width = 50
frame.origin.x = self.screenWidth - 50
self.scrollBar.frame = frame
}
}
我找到了在另一个StackOverflow帖子上进行百分比计算的代码的基础知识,但不可否认,我不是100%确定它在做什么/为什么它在我的演示应用程序中工作而不是真实的。我已经应用了不同的数字和计算但仍然无法正确使用它。
非常感谢任何帮助或见解。