UIRefreshcontrol在拉下并握住时会紧张不安

时间:2014-03-06 12:55:08

标签: ios objective-c ios7 pull-to-refresh uirefreshcontrol

我在tableviewcontroller中创建了一个UIRefreshcontrol,如下所示在viewdidload方法中:

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

问题是,当我把它拉下来一点点时,桌子就会抖动,给人一种非常不愉快的UI体验。有人可以帮忙吗?仅在横向模式下才会出现此行为。

这是我的代码:

-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;
    }

7 个答案:

答案 0 :(得分:17)

所以我遇到了同样的问题,我想出了一个解决方案。基本上,如果你将tableView拉得足够远并保持它,ValueChanged控件事件将在用户释放触摸之前触发。如果您刷新数据并在此时重新加载tableView,表格将会跳起来。

为了解决这个问题,我最终独立于ValueChanged事件刷新了表格。相反,我使用该事件以及scrollView委托方法仅在用户放手后刷新表。

首先,在viewDidLoad中设置refreshControl。

override func viewDidLoad()
{
    super.viewDidLoad()

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

ValueChanged方法很简单。如果我们已经停止了拖动,这在快速向下滑动后发生,只需使用您自己的自定义方法刷新表格。

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

然后,您需要实现didEndDragging。如果你已经拉得足够远,那么refreshControl将会刷新,所以调用刷新。否则,您要么已经拉得太远,要么拖动到表的另一部分,要么拖得太快以至于还没有触发refreshControl ValueChanged事件,它会在那里刷新表。

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

就是这样。在您停止拖动之前,表格不会重新加载,这可以避免您注意到的紧张跳跃。我知道这已经有一年了,但我希望这可以帮助其他人在Google上遇到这个问题。

答案 1 :(得分:2)

只需在tableView.alwaysBounceVertical = YES之后添加[refresh endRefreshing],因此刷新控件结束动画后,表格将弹回顶部。

答案 2 :(得分:1)

尝试更改

self.refreshControl = refresh;

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

+++++++++ 如果你在第一次刷新控件时触发了argumentsString布局的问题 - 在将refreshControl添加为子视图后添加它

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

答案 3 :(得分:1)

我的解决方案与接受的解决方案相似。想法是仅在正确的位置后更新表视图。因此,我们可以添加一个变量来跟踪是否需要在滚动视图完全弹回时更新视图(在减速时请勿更新)。

此外,请始终在结束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
    }
}

答案 4 :(得分:0)

通常使用UIRefreshControl来触发异步重载操作,并且应该在经过一段时间后调用endAnimating。它看起来就像刷新控件开始动画的那一刻,你立即结束它。这可能会让UIRefreshControl感到困惑。

尝试在经过一段时间后调用endAnimating,或者在另一个runloop循环中调用endAnimating(例如,在dispatch_async中调用它)。您的代码似乎存在其他问题(例如,您的tableView:cellForRowAtIndexPath:正在错误地创建单元格),因此可能存在潜伏的其他问题。

答案 5 :(得分:0)

SWIFT 4:

在ViewdidLoad()

someCollectionView或someTableView

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

完美地为我工作。

答案 6 :(得分:0)

@Devin的回答确实有所帮助,但对我而言,完全解决此问题的方法是将NavigationBar设置为“半透明”。 https://i.stack.imgur.com/TKcdH.png

由于某种原因触发UIControlEventValueChanged时,使用不透明的NavigationBar会使表视图略微跳动。

XCode 10.1