web-dev-qa-db-ja.com

iOS7のUICollectionViewでのUIRefreshControl

私のアプリケーションでは、コレクションビューでリフレッシュコントロールを使用しています。

UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:[UIScreen mainScreen].bounds];
collectionView.alwaysBounceVertical = YES;
...
[self.view addSubview:collectionView];

UIRefreshControl *refreshControl = [UIRefreshControl new];
[collectionView addSubview:refreshControl];

iOS7にはいくつかの厄介なバグがあり、コレクションビューをプルダウンして、更新の開始時に指を離さないと、垂直contentOffsetが20〜30ポイント下にシフトし、醜いスクロールジャンプが発生します。

UITableViewControllerの外で更新コントロールを使用すると、テーブルにもこの問題が発生します。しかし、それらの場合、UIRefreshControlインスタンスをUITableView_refreshControlというプライベートプロパティに割り当てることで簡単に解決できます。

@interface UITableView ()
- (void)_setRefreshControl:(UIRefreshControl *)refreshControl;
@end

...

UITableView *tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds];
[self.view addSubview:tableView];

UIRefreshControl *refreshControl = [UIRefreshControl new];
[tableView addSubview:refreshControl];
[tableView _setRefreshControl:refreshControl];

ただし、UICollectionViewにはそのようなプロパティがないため、手動で処理する方法が必要です。

31
Ilya Laktyushin

同じ問題があり、それを修正するように見える回避策を見つけました。

これは、スクロールビューのエッジを超えてプルすると、UIScrollViewがパンジェスチャの追跡を遅くするために発生しているようです。ただし、UIScrollViewは追跡中のcontentInsetへの変更を考慮していません。 UIRefreshControlがアクティブになるとcontentInsetが変更され、この変更が原因でジャンプが発生します。

setContentInsetUICollectionViewをオーバーライドし、このケースを考慮すると、次のように役立ちます。

- (void)setContentInset:(UIEdgeInsets)contentInset {
  if (self.tracking) {
    CGFloat diff = contentInset.top - self.contentInset.top;
    CGPoint translation = [self.panGestureRecognizer translationInView:self];
    translation.y -= diff * 3.0 / 2.0;
    [self.panGestureRecognizer setTranslation:translation inView:self];
  }
  [super setContentInset:contentInset];
}

興味深いことに、UITableViewは、更新コントロールのPASTをプルするまで追跡を遅くしないことでこれを考慮しています。ただし、この動作が公開される方法はわかりません。

51
Tim Norman
- (void)viewDidLoad
{
     [super viewDidLoad];

     self.refreshControl = [[UIRefreshControl alloc] init];
     [self.refreshControl addTarget:self action:@selector(scrollRefresh:) forControlEvents:UIControlEventValueChanged];
     [self.collection insertSubview:self.refreshControl atIndex:0];
     self.refreshControl.layer.zPosition = -1;
     self.collection.alwaysBounceVertical = YES;
 }

 - (void)scrollRefresh:(UIRefreshControl *)refreshControl
 {
     self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:@"Refresh now"];
     // ... update datasource
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"Updated %@", [NSDate date]]];
        [self.refreshControl endRefreshing];
        [self.collection reloadData];
     }); 

 }
1