Как я могу программно принудительно остановить прокрутку в UIScrollView?
Примечание. Ответ указанный здесь, не работает для меня.
У меня есть UIScrollView (а не табличное представление, только обычная вещь), и когда пользователь предпринимает определенные действия, я хочу убить любую прокрутку (перетаскивание или замедление) внутри представления. Я пробовал делать, например. это:
[scrollView scrollRectToVisible:CGRectInset([scrollView bounds], 10, 10) animated:NO];
по теории, что, учитывая, что уже известна видимая прямая, прокрутка будет просто останавливаться там, где она есть, но оказывается, что это не имеет никакого эффекта - видимо, в прокрутке видят, что данный rect находится в и не предпринимает никаких действий. Я может заставить прокрутку останавливаться, если я дам прямой, который определенно вне видимых в настоящее время границ, но внутри contentSize представления. Это, кажется, останавливает представление, как ожидалось... но также заставляет его перейти в другое место. Я мог бы немного поиграть на полях, чтобы заставить это работать достаточно хорошо, но знает ли кто-нибудь о чистом способе остановить просмотр прокрутки, который делает это?
Спасибо.
Ответы
Ответ 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;
Ответ 8
Этот ответ сработал у меня:
Деактивировать замедление UIScrollView
-(void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{
[scrollView setContentOffset:scrollView.contentOffset animated: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 или раскадровку, все, что вам нужно сделать, это перетащить жест панорамирования на рассматриваемое подпредставление.