UITableView 拉动刷新导致闪烁。如何预防?

Posted

技术标签:

【中文标题】UITableView 拉动刷新导致闪烁。如何预防?【英文标题】:UITableView pull to refresh causing flickering. How to prevent it? 【发布时间】:2012-02-27 01:35:23 【问题描述】:

我正在做下拉刷新的事情。在 scrollViewDidEndDecelerating 我检查偏移量是否超过某个点,在 scrollViewDidEndDragging 我设置 contentInset 以保持下拉部分可见。

但是,这会导致闪烁,可能是由于在滚动动画期间 contentInset 被重置。我想我可以通过在 scrollViewWillEndDragging 中设置 targetContentOffset 来防止这种情况,但它似乎并没有奏效。

 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 


     if (scrollView.contentOffset.y < -kRefreshViewDelta) 
     
         self.tableView.contentInset = UIEdgeInsetsMake(kRefreshViewHeight, 0.0f, 0.0f, 0.0f);

     


- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
 
     if (scrollView.contentOffset.y  < -kRefreshViewDelta) 
     
          targetContentOffset->y = kRefreshViewHeight ;
     
 

【问题讨论】:

【参考方案1】:

如果您完全更改分配给 UITableView 的框架(在滚动期间或其他情况下),则会导致 contentInset 重置为默认值 (0,0,0,0)。我的有一些状态检查,但基本上这就是我为我所做的......

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView
                  willDecelerate:(BOOL)decelerate 
  if (scrollView.contentOffset.y < -kRefreshDeltaY) 
    animation = ^
        [self setContentInset:UIEdgeInsetsMake(kRefreshDeltaY,
                                                          0, 0, 0)];
    ;

    [UIView animateWithDuration:0.3
                          delay:0
                        options:UIViewAnimationOptionAllowUserInteraction
                     animations:animation
                     completion:completion];
   // if

只要我不布置子视图或更改 UITableView 的框架,它对我来说就很好。

【讨论】:

【参考方案2】:

Mike 的回答对我有用(但我无法投票或评论它)。似乎将我的代码包装在动画块中消除了我的闪烁。

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 

    if (scrollView.contentOffset.y < 0 && scrollView.contentInset.top < 0)
    
        // shows table header view
        // setting inset without using animation block causes flicker
        [UIView animateWithDuration:0.1 animations:^
        
            scrollView.contentInset = UIEdgeInsetsZero;
        ];
    

    // hides table header view
    if (scrollView.contentOffset.y > 44 && scrollView.contentInset.top == 0)
    
        scrollView.contentInset = UIEdgeInsetsMake(-44, 0, 0, 0);
    

【讨论】:

谢谢。我从 44 中假设您还试图将搜索栏作为标题隐藏起来? @MusiGenesis 确实我隐藏了一个用户可以下拉使用但一旦用户不再使用它就会隐藏的搜索栏。【参考方案3】:

我尝试了一种不同的机制来刷新此拉动。请检查代码

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

    if (!reloading)
    
        checkForRefresh = YES;  //  only check offset when dragging
    


- (void)scrollViewDidScroll:(UIScrollView *)scrollView

    if (reloading) return;

    if (checkForRefresh) 
        if (refreshHeaderView.isFlipped
            && scrollView.contentOffset.y > -65.0f
            && scrollView.contentOffset.y < 0.0f
            && !reloading) 
            [refreshHeaderView flipImageAnimated:YES];
            [refreshHeaderView setStatus:kPullToReloadStatus];


         else if (!refreshHeaderView.isFlipped
                   && scrollView.contentOffset.y < -65.0f) 
            [refreshHeaderView flipImageAnimated:YES];
            [refreshHeaderView setStatus:kReleaseToReloadStatus];

        
    

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView
                  willDecelerate:(BOOL)decelerate

    if (reloading) return;

    if (scrollView.contentOffset.y <= - 65.0f) 
        if([self.tableView.dataSource respondsToSelector:
            @selector(reloadTableViewDataSource)])
            [self showReloadAnimationAnimated:YES];
            [self reloadTableViewDataSource];
        
    
    checkForRefresh = NO;
   


- (void)reloadTableViewDataSource

    [self performSelectorOnMainThread:@selector(refresh) withObject:nil waitUntilDone:NO];


【讨论】:

以上是关于UITableView 拉动刷新导致闪烁。如何预防?的主要内容,如果未能解决你的问题,请参考以下文章

拉动刷新uitableview json解析数据

如何使用刷新控件限制拉动距离?

UITableView上方的自定义UIView(用户拉动刷新时)

工作拉动以禁用反弹刷新

拉动刷新后,带有 UiRefreshControl 的 Tableview 卡住了

UITableView setContentOffSet 导致不必要的滚动到顶部