问题
I'm having some trouble on implementing a UIRefreshControl on a UITableView.
Everything is working fine except the fact that I have to scroll something like 80% of the screen for the UIRefreshControl to get triggered. Sometimes I'm not even able to trigger it since there is a tab bar on the bottom of the screen, which cancels the scrolling movement when the finger reaches it.
I've looked at other apps, namely Apple's 'Mail', where the UIRefreshControl is triggered after scrolling only 30% of the screen.
What am I missing? Really need help on this one!
Thanks in advance
回答1:
I had a similar problem and it's quite possible that's the same cause for you.
For me happens that I hided the scroll indicator making me unable to see the obvious cause of the problem: the UIScrollView
's height is much greater than its superView
...
Double check your UIScrollView
's height because the "dragging distance" it's just a percentage of that height. Same goes for UITableView
too, since it's a child class of UIScrollView
.
EDIT: Seems that this isn't the only way to reproduce this problem, since the required drag distance to trigger the refresher is calculated in a buggy way. Refer to this question for more info.
But in general it will happen if your UIScrollView
's height is different than his parent container (e.g the screen itself).
回答2:
You probably need to not use UIRefreshControl and just utilize scrollViewDidScroll (or tableViewDidScroll if a tableView) on handle your refresh accordingly since UIRefreshControl can't be modified.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if ((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height)
{
// Refresh from here
}
}
回答3:
After some extensive testing and playing around with UIKit I have come to a conclusion.
TL;DR
UIRefreshControl
isn't smart enough. To fix add this code in viewDidAppear
or viewDidLayoutSubviews
let refreshControl = scrollView.refreshControl
scrollView.refreshControl = nil
scrollView.refreshControl = refreshControl
Test setup
Single UIViewController
in a Storyboard with a UIView
as its view
which in turn has a UIScrollView
as only subview which in turn has a single UIView
as subview with top,right,bottom,left,width,height
constraints equal to superview
. The viewController has freeform size with 1200p
height.
In the subclass of the UIViewController
a UIRefreshControl
is added by setting the UIScrollView#refreshControl
to a new UIRefreshControl
inside viewDidLoad
.
When running the application in an iPhone X simulator
and dragging the scrollView to perform a "Pull to refresh" one must drag considerably longer to make the refreshControl animating and send its notification it was pulled down.
The problem
One of my hypotheses was that the UIRefreshControl
gets its dragging distance
set once it is added to the scrollView and since AutoLayout
hasen't updated the root view's subviews at viewDidLoad
the scrollView has a height of 1180.0p
instead of the correct 768.0p
thus the refreshControl's dragging distance
would be calculated for the height 1180.0p
instead of 768.0p
and thus become much longer than expected when running the app.
The solution
By updating the scrollView's refreshControl after the correct size for the scrollView has been set the correct dragging distance is calculated.
This update has to occur in a function where the correct size of the scrollView has been calculated, for example viewDidAppear
and viewDidLayoutSubviews
.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let refreshControl = scrollView.refreshControl
scrollView.refreshControl = nil
scrollView.refreshControl = refreshControl
}
来源:https://stackoverflow.com/questions/16360988/uitableview-dragging-distance-with-uirefreshcontrol