Подтвердить что ты не робот

Как я могу программно принудительно остановить прокрутку в UIScrollView?

Примечание. Ответ указанный здесь, не работает для меня.

У меня есть UIScrollView (а не табличное представление, только обычная вещь), и когда пользователь предпринимает определенные действия, я хочу убить любую прокрутку (перетаскивание или замедление) внутри представления. Я пробовал делать, например. это:

[scrollView scrollRectToVisible:CGRectInset([scrollView bounds], 10, 10) animated:NO];

по теории, что, учитывая, что уже известна видимая прямая, прокрутка будет просто останавливаться там, где она есть, но оказывается, что это не имеет никакого эффекта - видимо, в прокрутке видят, что данный rect находится в и не предпринимает никаких действий. Я может заставить прокрутку останавливаться, если я дам прямой, который определенно вне видимых в настоящее время границ, но внутри contentSize представления. Это, кажется, останавливает представление, как ожидалось... но также заставляет его перейти в другое место. Я мог бы немного поиграть на полях, чтобы заставить это работать достаточно хорошо, но знает ли кто-нибудь о чистом способе остановить просмотр прокрутки, который делает это?

Спасибо.

4b9b3361

Ответ 1

Я немного играл с вашим оригинальным решением, и это, похоже, работает отлично. Я думаю, что у вас это было почти так, но вы просто компенсировали право, которое вы использовали слишком много, и забыли, что вы можете просто прокрутить прямой прямо к исходному прямоугольнику.

Обобщенным решением для любого действия прокрутки является следующее:

- (void)killScroll 
{
    CGPoint offset = scrollView.contentOffset;
    offset.x -= 1.0;
    offset.y -= 1.0;
    [scrollView setContentOffset:offset animated:NO];
    offset.x += 1.0;
    offset.y += 1.0;
    [scrollView setContentOffset:offset animated:NO];
}

[Изменить] Начиная с iOS 4.3 (и, возможно, раньше) это также работает

- (void)killScroll 
{
    CGPoint offset = scrollView.contentOffset;
    [scrollView setContentOffset:offset animated:NO];
}

Ответ 2

Фактический общий ответ [scrollView setContentOffset:offset animated:NO] не совпадает с [scrollView setContentOffset:offset] !

  • [scrollView setContentOffset:offset animated:NO] фактически останавливает любую запущенную анимацию.
  • [scrollView setContentOffset:offset] не останавливает анимацию.
  • То же самое для scrollView.contentOffset = offset: не останавливает работающую анимацию.

Это нигде не задокументировано, но поведение, протестированное на iOS 6.1 и iOS 7.1 - возможно, также раньше.

Таким образом, решение остановить запущенную анимацию/замедление очень просто:

[scrollView setContentOffset:scrollView.contentOffset animated:NO];

Ну, в основном то, что сказал Дэвид Лю в своем отредактированном ответе. Но я хотел пояснить, что эти два API-интерфейса НЕ одинаковы.

Свифт 3:

scrollView.setContentOffset(scrollView.contentOffset, animated: false)

Ответ 3

Для меня Дэвид Луи принял ответ выше, не работал у меня. Это то, что я закончил:

- (void)killScroll {
    self.scrollView.scrollEnabled = NO;
    self.scrollView.scrollEnabled = YES;
}

Для чего это стоит, я использую iOS 6.0 iPhone Simulator.

Ответ 4

Это то, что я делаю для своих просмотров прокрутки и всех других связанных подклассов:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
 {
    *targetContentOffset = scrollView.contentOffset;
 }

Это устанавливает значение targetContentOffset в текущее смещение scrollView, что приводит к остановке прокрутки, поскольку она достигла цели. На самом деле имеет смысл использовать метод, целью которого является то, что пользователи могут установить целевой contentOffset.

Swift

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    targetContentOffset.pointee = scrollView.contentOffset
}

Ответ 5

Остановите прокрутку в быстро:

scrollView.setContentOffset(scrollView.contentOffset, animated: false)

Ответ 6

На самом деле... Самый "современный" способ был бы →

scrollview.panGestureRecognizer.enabled = false;
scrollview.panGestureRecognizer.enabled = true;

Это деактивирует распознаватель жестов, который отвечает за прокрутку всего лишь мгновение, которое убьет текущее касание. Пользователь должен будет поднять палец и вернуть его обратно, чтобы снова начать прокрутку.

Изменить: это фактически просто убивает текущее перетаскивание пользователя, но не сразу останавливает торможение, если scrollview находится в этом состоянии в настоящее время. Для этого принятые ответы на редактирование в значительной степени являются наилучшим способом xD

[scrollview setContentOffset: scrollview.contentOffset animated:false];

Ответ 7

Самый чистый способ будет подклассифицировать UIScrollView и предоставить собственный метод setContentOffset. Это сообщение должно быть отправлено, только если вы не включили логическое свойство freeze.

Так же:

BOOL freeze; // and the @property, @synthesize lines..

-(void)setContentOffset:(CGPoint)offset
{
    if ( !freeze ) [super setContentOffset:offset];
}

Затем, чтобы заморозить:

scrollView.freeze = YES;

Ответ 9

Я пробовал эти методы в коллекции:

self.collectionView.collectionViewLayout.finalizeCollectionViewUpdates()

Ответ 10

Это работает для меня в Swift 4.2:

   func killScroll() {
    self.scrollView.isScrollEnabled = false;
    self.scrollView.isScrollEnabled = true;
}

... как расширение:

extension UIScrollView {
    func killScroll() {
        self.isScrollEnabled = false;
        self.isScrollEnabled = true;

    }
}

Ответ 11

Я хотел отключить прокрутку только в том случае, если определенный вид UIView в представлении прокрутки является источником касания во время пролистывания. Для перемещения UIView за пределы UIScrollView потребовалось бы немало рефакторинга, поскольку у нас была сложная иерархия представлений.

В качестве обходного пути я добавил один UIPanGestureRecognizer в подпредставление, в котором я хотел предотвратить прокрутку. Этот UIPanGestureRecognizer будет cancelsTouchesInView, который предотвращает активацию panGesture UIScrollView.

Это немного "хак", но это очень легко изменить, и если вы используете XIB или раскадровку, все, что вам нужно сделать, это перетащить жест панорамирования на рассматриваемое подпредставление.