I want to add a little button in the bottom right corner of a UITableView. When we are in the top half of the tableview, the button programmatically scrolls you to the bottom, and when you are in the bottom half, it takes you to the top. And the button's icon changes from "goto top" to "goto bottom" or vice versa depending on the situation.
In my code below, the button works fine- you press it when you are at the top, you hit the bottom, and the button graphic changes to the "goto top" icon. However, dragging up and down like you would traditionally in a table doesn't make the button change it's icon properly. You even need to pull past the border (top or bottom) of the table to make it flip to the correct state.
When a button is pressed, if we are past halfway (as defined by a function pastHalfway), we go either to the top or bottom of the table. Something is wrong with it, but I've tussled a bit and basically made things not work well in various ways. I think the problem is I am not determining the midpoint content offset of the table correctly.
func pastHalfway() -> Bool {
// TODO: This doesn't work
let offset:CGPoint = self.tableView.contentOffset
let height:CGFloat = self.tableView.frame.height
println("pastHalfway offset.y=\(offset.y) height=\(height)")
return offset.y > (height/3.0) // 3.0 is 3/4 down the table
}
func gotoButtonPressed(sender: UIButton!) {
if let realPost = post {
if realPost.numberComments > 0 {
if self.pastHalfway() {
let indexPath:NSIndexPath = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Top, animated: true)
} else {
let indexPath:NSIndexPath = NSIndexPath(forRow: realPost.numberComments - 1, inSection: 1)
self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: true)
}
}
}
}
func maybeShowGotoButtons() {
let yOffset:CGFloat = self.tableView.contentOffset.y
if (self.post!.numberComments < minRowsToShowGotoButtons) {
// Hide and disable buttons
self.gotoButton.hidden = true
self.gotoButton.enabled = false
} else {
// Show buttons, depending on content offset
if self.pastHalfway() {
self.gotoButton.setImage(UIImage(named: "gotoTopIcon"), forState: .Normal)
} else {
self.gotoButton.setImage(UIImage(named: "gotoBottomIcon"), forState: .Normal)
}
// And enable
self.gotoButton.hidden = false
self.gotoButton.enabled = true
}
}
UIScrollView Delegates
override func scrollViewWillBeginDragging(scrollView: UIScrollView) {
UIView.animateWithDuration(0.1, animations: {
self.gotoButton.alpha = 0.5
})
}
override func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
UIView.animateWithDuration(0.2, animations: {
self.gotoButton.alpha = 1.0
self.maybeShowGotoButtons()
})
}
override func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
// This is used for the programmatic scroll top/bottom when clicking buttons
self.maybeShowGotoButtons()
}
The necessary fixes were adding 1)
override func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
self.maybeShowGotoButtons()
}
2)
func atBottom() -> Bool {
let height = self.tableView.contentSize.height - self.tableView.frame.size.height
if self.tableView.contentOffset.y < 10 {
//reach top
return false
}
else if self.tableView.contentOffset.y < height/2.0 {
//not top and not bottom
return false
}
else {
return true
}
}