I'm trying to implement a UIRefreshControl
in my project on a UICollectionView
. It works as intended, but I need to pull the the UICollectionView
about 3x as much as the height of the refreshControl
when it's spinning (once the user has let go). I've seen other apps where you only need to pull down to the height of the refreshControl
when it's spinning. How do I change the amount I need to pull down?
Code:
(void)viewDidLoad { [super viewDidLoad]; [self.collectionView setBackgroundColor:[UIColor clearColor]]; self.refreshControl = [UIRefreshControl new]; [self.refreshControl addTarget:self action:@selector(refreshFavorites) forControlEvents:UIControlEventValueChanged]; [self.collectionView addSubview:self.refreshControl]; self.collectionView.alwaysBounceVertical = YES; }
Attached are pictures to help visualize what I mean. My collectionView
has one row (solid red). The space between the red and the refreshControl
is simply the space I'm pulling down to try to activate the refreshControl
.
In this image I've almost activated the control and I've already pulled down a considerable amount on the screen.
In this image I've activated the control and it's starting to load (after it jumps ~20-30 pix, but it still highlights how significant this is)
This image shows the control in its "resting" state after it's been activated and is doing the animation.
I've tried setting the frame of the UIRefreshControl
to try to control the height, but this doesn't work. I've also changed around the size in collectionView:layout:sizeForItemAtIndexPath
which hasn't helped.
A standard control that can initiate the refreshing of a scroll view’s contents. A UIRefreshControl object is a standard control that you attach to any UIScrollView object, including table views and collection views.
UIRefreshControl isn’t available when the user interface idiom is UIUserInterfaceIdiom. mac. However, you can update your app to provide similar functionality in the Mac idiom. For example, replace the control with a Refresh menu item by creating a UIKeyCommand object with the title “Refresh” and the keyboard shortcut Command-R.
The refresh control lets you know when to update your content using the target-action mechanism of UIControl. Upon activation, the refresh control calls the action method you provided at configuration time. When adding your action method, configure it to listen for the valueChanged event, as shown in the following example code.
If a UIRefreshControl needs to be pulled down too far to trigger, it might be a bug of iOS SDK.
I recommend solve this situation with a view controller’s help:
- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; // Force update the snapping height of refresh control. [self.refreshControl didMoveToSuperview]; }
Also if you don’t mind use private API and needs more accurate control, you can write like this:
- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; @try { [self.refreshControl setValue:@(60) forKey:@"_snappingHeight"]; } @catch (NSException *exception) { } }
This works on iOS 7-10. No App Store review issue.
Look inside
UIRefreshControl has a property called snappingHeight. This property controls the distance user needs pull down. But unfortunately, this value not set properly always, especially you have a custom view hierarchy.
UIRefreshControl have a private method calls _updateSnappingHeight
, this method also called in didMoveToSuperview
. So an manual didMoveToSuperview
call can update the wrong snapping value.
For people still looking for an answer to this. I have a definite and best possible answer so far...
SWIFT 3:
Inside viewDidLoad() :
self.refresher = UIRefreshControl() self.refresher.tintColor = UIColor.red self.scrollView.addSubview(self.refresher)
Next If your View is a ViewController - implement the ScrollViewDelegate like so:
class YourViewController: UIViewController, UIScrollViewDelegate
Once you have your scrollView @IBOulet linked... Go ahead and set the scrollView delegate to self inside viewDidLoad() like so:
self.scrollView.delegate = self
Next, since you have the delegates set up, set up the scrollViewDidScroll Function and implement it, to check if the person pulled down passed -90 like so :
func scrollViewDidScroll(_ scrollView: UIScrollView) { if scrollView == self.scrollView { if scrollView.contentOffset.y < -90 && !self.refresher.isRefreshing{ self.refresher.beginRefreshing() self.Refresh() print("zz refreshing") } } }
Now, notice we do not have the
self.refresher.addTarget(self, action: #selector(self.Refresh()), for: UIControlEvents.valueChanged)
and nor do we need it at all. Instead we are calling beginRefresh() followed by the actual function... Just make sure to call endRefresh() somewhere you want it to end.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With