UIRefreshcontrol jitters when pulled down and held

喜夏-厌秋 提交于 2020-01-01 04:36:12

问题


I have created a UIRefreshcontrol in my tableviewcontroller as follows in the viewdidload method :

    refresh = [UIRefreshControl.alloc init];
    refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"];
    [refresh addTarget:self action:@selector(refreshChatsTableView) forControlEvents:UIControlEventValueChanged];
    self.refreshControl = refresh;

the problem is that when I pull it down a little long , the table jitters up giving a pretty unpleasant UI experience. Can anyone please help ? This behavior is experienced only in the Landscape mode.

Here is my code :

-UIRefreshControl  *refresh;

    -(void)viewDidLoad{
        [super viewDidLoad];
         arr= [[NSArray    alloc]initWithObjects:@"A",@"B",@"C",@"D",@"E",@"A",@"B",@"C",@"D",@"E", nil];

        //refresh control
        refresh = [UIRefreshControl.alloc init];
        refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to   Refresh"];
        [refresh addTarget:self action:@selector(refreshChatsTableView)  forControlEvents:UIControlEventValueChanged];
        self.refreshControl = refresh;
      }


    -(void)refreshChatsTableView{
        [refresh endRefreshing];
    }

    -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
        return 1;
    }

    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
       return arr.count;
    }

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        static NSString *CellIdentifier = @"Cell";
        UITableViewCell *cell =[[UITableViewCell alloc]init];
        cell.textLabel.text = [arr objectAtIndex:indexPath.row ];

        return cell;
    }

回答1:


So I just came across this same problem, and I came up with a solution. Basically, if you pull your tableView down far enough and hold it, the ValueChanged control event will fire before the user releases the touch. If you refresh your data and reload the tableView at this point, the table will jump up.

To combat this, I ended up refreshing the table independently of the ValueChanged event. Instead, I used that event, along with the scrollView delegate methods, to only refresh the table after the user had let go.

So first, set up your refreshControl in viewDidLoad.

override func viewDidLoad()
{
    super.viewDidLoad()

    refreshControl = UIRefreshControl()
    refreshControl?.addTarget(self, action: "refreshControlChanged", forControlEvents: UIControlEvents.ValueChanged)
}

The ValueChanged method is simple. If we've already stopped dragging, which happens after a quick swipe down, just refresh the table using your own custom method.

internal func refreshControlChanged()
{
    if !tableView.dragging
    {
        refresh()
    }
}

Then, you need to implement didEndDragging. If you've pulled down far enough, the refreshControl will be refreshing, so call refresh. Otherwise, you either haven't pulled down far enough, you were dragging on a different part of the table, or you dragged so quickly that the refreshControl ValueChanged event has yet to fire, and it will refresh the table there.

override func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool)
{
    if refreshControl?.refreshing == true
    {
        refresh()
    }
}

And that's it. The table won't get reloaded until after you've stopped dragging it, which avoids the jittery jump that you noticed. I know this is a year old, but I hope this helps anyone else coming across this on Google.




回答2:


try changing

self.refreshControl = refresh;

for

[self.tableView addSubview:refresh];
[self.tableView sendSubviewToBack:refresh];

+++++++++ if u have problem with attributedString layout with first refreshControl triggered - add this after adding refreshControl as subview

dispatch_async(dispatch_get_main_queue(), ^{
    [refreshControl beginRefreshing];
    [refreshControl endRefreshing];
});



回答3:


Just add tableView.alwaysBounceVertical = YES after your [refresh endRefreshing] so table will bounce to top after the refresh control ended its animation.




回答4:


My solution is similar to the accepted solution. The idea is to update your table view only after the view is at the right place. Therefore, we can add a variable to track if we need to update the view when the scroll view is completely bounced back (don't update it while decelerating).

Also, always update your table view before ending the refreshControl.

// The action function of refreshControl
@objc private func refresh() {
    DispatchQueue.global(qos: .utility).async {
        // Update data
        // ......

        // Update the table view
        DispatchQueue.main.async {
            if self.tableView.isDragging == false {
                self.tableView.reloadData()
                self.myRefreshControl.endRefreshing()
            } else {
                self.needEndRefreshing = true
            }
        }
    }
}

override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    if self.needEndRefreshing {
        self.tableView.reloadData()
        self.myRefreshControl.endRefreshing()
        self.needEndRefreshing = false
    }
}



回答5:


Usually you use UIRefreshControl to trigger an asynchronous reload operation, and endAnimating should be called after a certain period of time has elapsed. It looks here like the moment the refresh control begins animating, you're ending it immediately. This is probably confusing UIRefreshControl.

Try calling endAnimating after a period of time has elapsed, or in another runloop cycle (e.g. call it in dispatch_async). There appear to be other problems with your code (for example, your tableView:cellForRowAtIndexPath: is creating cells incorrectly), so there might be other problems lurking in there.




回答6:


SWIFT 4:

In ViewdidLoad()

someCollectionView or someTableView

someCollectionView.refreshControl?.addSubview(refreshControl)
someCollectionView.refreshControl?.sendSubview(toBack: refreshControl)

Worked perfectly for me.




回答7:


@Devin's answer did help but what completely fixed the issue for me was to make my NavigationBar "Translucent". https://i.stack.imgur.com/TKcdH.png

Using non translucent NavigationBar causes the tableview to jump up slightly when UIControlEventValueChanged is fired for some reason.

XCode 10.1



来源:https://stackoverflow.com/questions/22225207/uirefreshcontrol-jitters-when-pulled-down-and-held

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!