Reputation: 7551
I have swift 2.0 ios app with storyboard. I have a tableViewController and in each row I have scrollView (with user scrolling disabled). Inside this scrollView I have an image, which fits scroll's size and it's a bit taller. Thing is I want to achieve "floating" effect on this image, when tableView is scrolled. Here's a code:
override func scrollViewDidScroll(scrollView: UIScrollView) {
let cells = tableView.visibleCells
let offsetY = scrollView.contentOffset.y
var diff:CGFloat = (offsetY - lastY) / 10
for cell in cells {
let indexPath = tableView.indexPathForCell(cell)!
let scroll = cell.viewWithTag(102) as! UIScrollView
let oldY = scroll.contentOffset.y
let newY = oldY + diff
let height = scroll.contentSize.height
if(newY >= 0 && newY + cellHeight < height){
scroll.contentOffset = CGPointMake(scroll.contentOffset.x, newY)
}
if(indexPath.row == 0){
print("\(oldY) + \(diff) = \(newY)")
}
}
lastY = offsetY
}
What I'm doing here is calculating difference of tableView scroll position (variable "diff"), get all visible cells and scroll scrollView's by that difference (divided by 10 and in opposite direction). When I scroll fast it's somehow working, but when I scroll very slowly nothing is moving.
When I'm slowly scrolling I'm getting output like this (last print):
15.5 + 0.05 = 15.55
15.5 + 0.05 = 15.55
15.5 + 0.05 = 15.55
15.5 + 0.05 = 15.55
15.5 + 0.05 = 15.55
15.5 + 0.05 = 15.55
15.5 + 0.05 = 15.55
When diff is too small scrollView is somehow truncating (or rounding) a result.
When I'm scrolling faster:
23.0 + 0.25 = 23.25
23.5 + 0.25 = 23.75
24.0 + 0.15 = 24.15
24.0 + 0.25 = 24.25
24.5 + 0.25 = 24.75
25.0 + 0.25 = 25.25
25.5 + 0.25 = 25.75
Here you can see it's suming up, but some results does not match (sum of line x should be first number in the next line).
It's not an issue with CGFloat as simple example shows:
var sum:CGFloat = 0
for(var i = 0; i < 10; i++){
let number:CGFloat = 0.05
sum += number
print(sum)
}
Results in:
0.05
0.1
0.15
0.2
0.25
0.3
0.35
0.4
0.45
0.5
How can I fix it? Maybe I should use a different approach to get similar effect?
Upvotes: 1
Views: 686
Reputation: 591
Apparently one can also override the contentOffset
property in the custom subclass like this:
var unrounded: CGPoint?
override var contentOffset: CGPoint {
get {
return unrounded ?? .zero
}
set {
unrounded = newValue
super.contentOffset = newValue
}
}
This has the advantage that it also works when calling setContentOffset(_:animated:)
, not only when assigning to contentOffset
.
Upvotes: 0
Reputation: 3397
UIScrollView.contentOffset is rounded to 0.5 on retina displays (0.33 on iPhone 6+) when set.
I suggest creating custom UITableViewCell subclass (if you don't have it yet) and create custom variable inside it:
class MyCell: UITableViewCell {
var unroundedContentOffsetY: CGFloat {
didSet {
scroll.contentOffset = CGPoint(x: scroll.contentOffset.x, unroundedContentOffsetY)
}
}
}
Then make calculations on cell.unroundedContentOffsetY
variable instead of cell.scroll.contentOffset
Upvotes: 5