UITableView w/ paging & momentum

2019-03-21 22:52发布

问题:

OBSERVATIONS

I've discovered some "weird" things about how UITableViews / UIScrollViews scroll in Objective-C for iOS after you've lifted your finger:

  • A scroll view's "velocity" (as in scrollViewWillEndDragging:withVelocity:targetContentOffset:) is not based in time but rather based in "render" or "frame refresh" or the like; i.e., a "velocity" of 3.0 means that the scroll view will scroll 3.0 points before the next refresh, at which point it will scroll yet another 3.0 points if the "velocity" is still 3.0. (in contrast to an absolute time-based velocity)

  • "Refreshes" occur approx. 950 times per second, but this varies and is not dependable. (again, in contrast to an absolute time-based refresh rate)

  • Because UIScrollViews decelerate exponentially rather than linearly, decelerationRate is a geometric constant. This means that on every "refresh" of the scroll view, its "velocity" is set to its previous velocity times the "deceleration rate".

  • At some point, the scroll view's velocity is close enough to zero that it stops scrolling. I am not sure what this threshold is yet.


DESIRED BEHAVIOR / PROBLEM

I've derived an equation that can theoretically be solved to adjust the deceleration rate so that the scroll view can scroll naturally with momentum and settle close enough to the top of a table view cell to mimic "paging." (I also have an animation added to scrollViewDidEndDragging:willDecelerate: to adjust the content offset minimally. Adjusting content offset w/o adjust decelerationRate looks weird; the scroll view either jumps ahead or lurches backwards suddenly.)

This equation is: Ad^n + Bd + C = 0 where d = decelerationRate. Ideally I'd like something in the form of d(n, A, B, C), but my math PhD friend tells me that's not deterministically possible. He pointed me towards the following page: http://en.wikipedia.org/wiki/Root-finding_algorithm

I've also found that I can't animate a scroll view to a predetermined content offset using animation style UIViewAnimationCurveEaseOut because setContentOffset:animated: doesn't take an options: parameter. Otherwise I would "fake" scrolling to my precalculated content offset.

(I found this on SO but it didn't work for me: UIScrollview setContentOffset with non linear animation ?)

I'd like to use a table view because all of my elements in my scroll view will be cells essentially, and table views are best for displaying a list of cells. However, based on my difficulty getting my desired behavior, I might just make a paging scrollview, which will probably be easier. I can then just limit the number of "cells" visible in my custom "table view" or else load them post-hoc as necessary.


What are your ideas / thoughts / suggestions?

So far I have not found existing examples of what I would like.


ILLUSTRATION

OR

回答1:

So this answer was obtained via a snarky but brilliant user on the #iphonedev IRC channel!

From within scrollViewWillEndDragging:withVelocity:targetContentOffset: you can just re-set the targetContentOffset to whatever you desire via *targetContentOffset = newTargetOffset;! Incredibly simple and elegant.

My mistake was trying to call [scrollview setContentOffset:newTargetOffset animated:YES] from within scrollViewWillEndDragging:withVelocity:targetContentOffset:, which didn't work at all, and therefore I set out to "solve" my problem in a more convoluted way that also didn't work at all.