82

UIScrollViewアプリにはすでに約 5 があり、すべて複数の.xibファイルをロードしています。を使用したいと思いますUIRefreshControl。これらは、UITableViewControllers で使用するために構築されています (UIRefreshControl クラス リファレンスによる)。5つすべてがどのように機能するかをやり直したくありませんUIScrollViewUIRefreshControl私はすでに で を使用しようとしUIScrollViewましたが、いくつかのことを除いて期待どおりに動作します。

  1. 更新イメージがローダーに変わった直後に、約 10 ピクセル下にジャンプします。これは、非常にゆっくりと下にUIScrollViewドラッグするように非常に注意している場合にのみ発生しません。UIScrollview

  2. 下にスクロールしてリロードを開始してからを放すと、放した場所UIScrollViewUIScrollViewとどまります。リロードが終了するUIScrollViewと、 はアニメーションなしで一番上にジャンプします。

これが私のコードです:

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

時間を節約して aUIRefreshControlで aを使用する方法はありUIScrollViewますか?

ありがとうございました!!!

4

11 に答える 11

97

私は でUIRefreshControl動作するようになりましたUIScrollView:

- (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");
        });
    });
}

別のスレッドでデータの更新を行う必要があります。そうしないと、メイン スレッド (UI が UI の更新に使用するスレッド) がロックされます。そのため、メイン スレッドがデータの更新でビジー状態になっている間、UI もロックされたりフリーズしたりして、滑らかなアニメーションやスピナーが表示されなくなります。

編集: わかりました、私は OP と同じことをしており、テキストを追加しました (つまり、「Pull to Refresh」)。そのテキストを更新するには、メイン スレッドに戻る必要があります。

回答を更新しました。

于 2013-02-21T17:08:18.120 に答える
47

上記の回答に加えて、場合によっては contentSize を設定できない (おそらく自動レイアウトを使用しますか?) か、contentSize の高さが UIScrollView の高さ以下です。このような場合、UIScrollView がバウンスしないため、UIRefreshControl は機能しません。

これを修正するには、プロパティalwaysBounceVerticalTRUEに設定します。

于 2013-12-04T15:55:01.017 に答える
14

幸運にも iOS 10 以降をサポートしている場合は、refreshControlの を簡単に設定できるようになりましたUIScrollView。これは、既存のrefreshControlonと同じように機能しUITableViewます。

于 2016-07-28T01:05:18.183 に答える
11

これをC#/Monotouchで行う方法は次のとおりです。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 ();
        });
    });
}
于 2013-03-22T02:52:50.210 に答える
2

Jumping の問題については、Tim Norman の回答で解決します。

swift2 を使用している場合の迅速なバージョンは次のとおりです。

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)
            }
        }
    }
}
于 2016-01-19T04:05:32.260 に答える
1

UIRefreshControl内部でちゃんと動くようにしましUIScrollViewた。contentInset の変更を継承しUIScrollView、ブロックし、contentOffset セッターをオーバーライドしました。

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)
            }
        }
    }
}
于 2014-12-05T16:06:37.520 に答える
-3

更新コントロールのインスタンスを作成して、スクロールビューの上部に追加するだけです。次に、デリゲートメソッドで、その動作を要件に合わせて調整します。

于 2013-02-20T12:36:33.147 に答える