Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIRefreshControl needs to be pulled down too far

Tags:

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.

enter image description here

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)

enter image description here

This image shows the control in its "resting" state after it's been activated and is doing the animation.

enter image description here

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.

like image 660
LyricalPanda Avatar asked Mar 05 '15 19:03

LyricalPanda


People also ask

What is a uirefreshcontrol?

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.

How do I use uiuirefreshcontrol on a Mac application?

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.

What is refresh control in uicontrol?

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.


2 Answers

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.

like image 112
BB9z Avatar answered Sep 30 '22 14:09

BB9z


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.

like image 20
amirkrd Avatar answered Sep 30 '22 13:09

amirkrd