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, который исправлен.

Это одно изменение решило мою проблему.