UIRefreshControl нужно слишком сильно снести
Я пытаюсь реализовать UIRefreshControl
в моем проекте на UICollectionView
. Он работает по назначению, но мне нужно потянуть UICollectionView
примерно на 3 раза больше, чем высота refreshControl
, когда она вращается (как только пользователь отпустил). Я видел другие приложения, где вам нужно только спуститься на высоту refreshControl
, когда она вращается. Как изменить сумму, которую мне нужно снять?
код:
(void)viewDidLoad {
[super viewDidLoad];
[self.collectionView setBackgroundColor:[UIColor clearColor]];
self.refreshControl = [UIRefreshControl new];
[self.refreshControl addTarget:self action:@selector(refreshFavorites) forControlEvents:UIControlEventValueChanged];
[self.collectionView addSubview:self.refreshControl];
self.collectionView.alwaysBounceVertical = YES;
}
Прикрепленные изображения, которые помогают визуализировать, что я имею в виду. Мой collectionView
имеет одну строку (сплошной красный). Пространство между красным и refreshControl
- это просто пространство, которое я пытаюсь активировать refreshControl
.
На этом изображении я почти активировал элемент управления, и я уже снял значительную сумму на экране.
![enter image description here]()
На этом изображении я активировал элемент управления и начал его загружать (после того, как он скачет ~ 20-30 пикселей, но он все еще подчеркивает, насколько это важно)
![enter image description here]()
Это изображение показывает элемент управления в состоянии "покоя" после его активации и выполняет анимацию.
![enter image description here]()
Я попытался установить кадр UIRefreshControl
, чтобы попытаться управлять высотой, но это не сработает. Я также изменил размер в collectionView:layout:sizeForItemAtIndexPath
, который не помог.
Ответы
Ответ 1
Если UIRefreshControl необходимо сместить слишком далеко для запуска, это может быть ошибкой SDK iOS.
Я рекомендую решить эту ситуацию с помощью справки диспетчера видов:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Force update the snapping height of refresh control.
[self.refreshControl didMoveToSuperview];
}
Также, если вы не используете частный API и вам нужен более точный контроль, вы можете написать вот так:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
@try {
[self.refreshControl setValue:@(60) forKey:@"_snappingHeight"];
}
@catch (NSException *exception) {
}
}
Это работает на iOS 7-10. Нет проблемы с проверкой в App Store.
Просмотр
UIRefreshControl имеет свойство snappingHeight. Это свойство управляет расстоянием, которое требуется пользователю. Но, к сожалению, это значение не устанавливается должным образом всегда, особенно у вас есть настраиваемая иерархия представлений.
UIRefreshControl имеет закрытый вызов метода _updateSnappingHeight
, этот метод также вызывается в didMoveToSuperview
. Таким образом, ручной вызов didMoveToSuperview
может обновить неверное значение привязки.
Ответ 2
Для людей, которые все еще ищут ответ на этот вопрос. У меня есть определенный и наилучший ответ до сих пор...
SWIFT 3:
Внутри viewDidLoad():
self.refresher = UIRefreshControl()
self.refresher.tintColor = UIColor.red
self.scrollView.addSubview(self.refresher)
Далее Если ваш View является ViewController - реализует ScrollViewDelegate следующим образом:
class YourViewController: UIViewController, UIScrollViewDelegate
Как только у вас есть связанный с scrollView @IBOulet...
Перейдите и установите делегат scrollView для самостоятельного просмотра viewDidLoad() следующим образом:
self.scrollView.delegate = self
Далее, поскольку у вас есть настроенные делегаты, настройте функцию scrollViewDidScroll и реализуйте ее, чтобы проверить, не спустился ли человек -90 так:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == self.scrollView
{
if scrollView.contentOffset.y < -90 && !self.refresher.isRefreshing{
self.refresher.beginRefreshing()
self.Refresh()
print("zz refreshing")
}
}
}
Теперь заметьте, что у нас нет
self.refresher.addTarget(self, action: #selector(self.Refresh()), for: UIControlEvents.valueChanged)
и нам это вообще не нужно. Вместо этого мы вызываем beginRefresh(), за которым следует фактическая функция... Просто убедитесь, что вы вызываете endRefresh(), где хотите, чтобы она закончилась.
Ответ 3
У меня была проблема с этим в iOS 10.2 Итак, для тех, кто по-прежнему страдает от этого, я нашел способ сделать это без необходимости касаться частных методов API (хотя это также устранило проблему).
Я обнаружил, что у меня возникла проблема, когда устройство вращалось на iPad. UIRefreshControl вел себя нормально на портрете, но начал вращаться, когда устройство было повернуто. После этого неважно, в какой ориентации он находился, его всегда нужно перетаскивать слишком далеко, чем нужно для активации.
Мое решение было основано на этом ответе: Смещение UIRefreshControl
Я попытался установить кадр UIRefreshControl всякий раз, когда устройство повернулось, и оно сработало. Он не идеален, поскольку он не использует AutoLayout, но его немного чище, чем игра с частными API.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
-(void)didRotate:(NSNotification *)notification {
[self.refreshControl setFrame:CGRectMake(0, 0, 20, 20)];
[self.refreshControl setNeedsLayout];
}
Ответ 4
Ни одно из решений, перечисленных здесь, не сработало для меня. Решение, которое я нашел, использует refresh.didMoveToSuperview()
в viewDidAppear
.
Комплексное решение:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
refresh.didMoveToSuperview()
}
Ответ 5
В моем случае я обнаружил проблему с имитируемым размером UIviewcontroller, который был свободен.
Я просто делаю изменения в смоделированном размере UIViewcontroller, который исправлен.
Это одно изменение решило мою проблему.