我可以在UIScrollView中使用UIRefreshControl吗?

我有约5个UIScrollView已经在我的应用程序,所有加载多个.xib文件。 我们现在想要使用UIRefreshControl 。 它们被构build为与UITableViewControllers一起使用(每个UIRefreshControl类的引用)。 我不想重新做5个UIScrollView工作。 我已经尝试在我的UIScrollView使用UIRefreshControl ,除了一些事情之外,它的工作方式和预期一样。

  1. 在刷新图像变成加载程序之后, UIScrollView向下跳跃约10个像素,这在我非常小心地非常缓慢地拖动UIScrollview时候才会发生。

  2. 当我向下滚动并启动重新加载,然后放开UIScrollViewUIScrollView停留在我放开的位置。 完成重新加载后, UIScrollView跳转到顶部,没有animation。

这是我的代码:

 -(void)viewDidLoad { UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; [refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged]; [myScrollView addSubview:refreshControl]; } -(void)handleRefresh:(UIRefreshControl *)refresh { // Reload my data [refresh endRefreshing]; } 

有什么办法可以节省一大堆时间,并在UIScrollView使用UIRefreshControl

谢谢!!!

我有一个UIRefreshControlUIScrollView一起工作:

 - (void)viewDidLoad { UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; scrollView.userInteractionEnabled = TRUE; scrollView.scrollEnabled = TRUE; scrollView.backgroundColor = [UIColor whiteColor]; scrollView.contentSize = CGSizeMake(500, 1000); UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; [refreshControl addTarget:self action:@selector(testRefresh:) forControlEvents:UIControlEventValueChanged]; [scrollView addSubview:refreshControl]; [self.view addSubview:scrollView]; } - (void)testRefresh:(UIRefreshControl *)refreshControl { refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:@"Refreshing data..."]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [NSThread sleepForTimeInterval:3];//for 3 seconds, prevent scrollview from bouncing back down (which would cover up the refresh view immediately and stop the user from even seeing the refresh text / animation) dispatch_async(dispatch_get_main_queue(), ^{ NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"MMM d, h:mm a"]; NSString *lastUpdate = [NSString stringWithFormat:@"Last updated on %@", [formatter stringFromDate:[NSDate date]]]; refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:lastUpdate]; [refreshControl endRefreshing]; NSLog(@"refresh end"); }); }); } 

需要在单独的线程上进行数据更新,否则会locking主线程(UI用来更新UI)。 所以,当主线程忙于更新数据时,UI也被locking或冻结,并且永远不会看到平滑的animation或微调。

编辑:好的,我做了同样的事情作为OP,我现在已经添加了一些文本(即“拉到刷新”),它需要回到主线程来更新该文本。

更新了答案。

添加上面的答案,在某些情况下,您不能设置contentSize(也许使用自动布局?),或contentSize的高度小于或等于UIScrollView的高度。 在这些情况下,UIRefreshControl将不起作用,因为UIScrollView不会反弹。

为了解决这个问题,将属性alwaysBounceVertical设置为TRUE

如果当你有幸支持iOS 10+,你现在可以简单地设置UIScrollViewrefreshControl 。 这与以前在UITableView上的refreshControl

这里是你如何在C#/ Monotouch中做到这一点。 我无法find任何C#任何样品,所以在这里..谢谢Log139!

 public override void ViewDidLoad () { //Create a scrollview object UIScrollView MainScrollView = new UIScrollView(new RectangleF (0, 0, 500, 600)); //set the content size bigger so that it will bounce MainScrollView.ContentSize = new SizeF(500,650); // initialise and set the refresh class variable refresh = new UIRefreshControl(); refresh.AddTarget(RefreshEventHandler,UIControlEvent.ValueChanged); MainScrollView.AddSubview (refresh); } private void RefreshEventHandler (object obj, EventArgs args) { System.Threading.ThreadPool.QueueUserWorkItem ((callback) => { InvokeOnMainThread (delegate() { System.Threading.Thread.Sleep (3000); refresh.EndRefreshing (); }); }); } 

对于跳跃问题, Tim Norman的答案解决了这个问题。

如果你使用的是swift2,这里是swift的版本:

 import UIKit class NoJumpRefreshScrollView: UIScrollView { /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. override func drawRect(rect: CGRect) { // Drawing code } */ override var contentInset:UIEdgeInsets { willSet { if self.tracking { let diff = newValue.top - self.contentInset.top; var translation = self.panGestureRecognizer.translationInView(self) translation.y -= diff * 3.0 / 2.0 self.panGestureRecognizer.setTranslation(translation, inView: self) } } } } 

我使UIRefreshControlUIScrollView正常工作。 我inheritance了UIScrollView ,阻止了contentInset的改变并且overrided contentOffset setter:

 class ScrollViewForRefreshControl : UIScrollView { override var contentOffset : CGPoint { get {return super.contentOffset } set { if newValue.y < -_contentInset.top || _contentInset.top == 0 { super.contentOffset = newValue } } } private var _contentInset = UIEdgeInsetsZero override var contentInset : UIEdgeInsets { get { return _contentInset} set { _contentInset = newValue if newValue.top == 0 && contentOffset.y < 0 { self.setContentOffset(CGPointZero, animated: true) } } } } 

如何在Swift 3中做到这一点:

 override func viewDidLoad() { super.viewDidLoad() let scroll = UIScrollView() scroll.isScrollEnabled = true view.addSubview(scroll) let refreshControl = UIRefreshControl() refreshControl.addTarget(self, action: #selector(pullToRefresh(_:)), for: .valueChanged) scroll.addSubview(refreshControl) } func pullToRefresh(_ refreshControl: UIRefreshControl) { // Update your conntent here refreshControl.endRefreshing() } 

您可以简单地创build一个刷新控件的实例,并将其添加到滚动视图的顶部。 那么在委托方法中,您将根据您的要求调整其行为。