UIRefreshControl с UICollectionView в iOS7
В моем приложении я использую управление обновлением с представлением коллекции.
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
не имеет такого свойства, поэтому должен быть какой-то способ справиться с ним вручную.
Ответы
Ответ 1
Имея ту же проблему и нашел обходное решение, которое, похоже, исправляет его.
Это похоже на то, что UIScrollView
замедляет отслеживание жесты панорамы, когда вы тянете за край прокрутки. Однако UIScrollView
не учитывает изменения в contentInset во время отслеживания. UIRefreshControl
изменяет содержимое. Вводится, когда он активируется, и это изменение вызывает скачок.
Переопределение setContentInset
на вашем UICollectionView
и учет этого случая помогает:
- (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 на управление обновлением. Однако я не вижу способа, которым это поведение подвергается.
Ответ 2
- (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];
});
}