Как отключить горизонтальную прокрутку UIScrollView?


92

У меня есть UIViewтрамплин как у iPhone. Я создал его с помощью UIScrollViewи UIButtons. Я хочу отключить горизонтальную прокрутку в указанном scrollview. Хочу только вертикальную прокрутку. Как мне этого добиться?


5
Вам следует изменить свой заголовок: вы просите горизонтальное в вопросе и вертикальное в заголовке. Люди находят ваши вопросы позже в поисковых системах, так что через 2 года это все еще имеет значение :)
— Жюльен

@RahulVyas Человек выше прав. Изменение названия уменьшит путаницу для новичков, которые попадают сюда через поисковую систему (например, я;)).
— SpacyRicochet

Отредактировали заголовок от имени автора. (Хотя в настоящее время он ожидает экспертной оценки, прежде чем редактирование станет видимым.)
— Дункан Бэббидж

Ответы:


125

Вы должны установить contentSizeсвойство UIScrollView. Например, если ваш UIScrollViewразмер составляет 320 пикселей (ширина экрана), вы можете сделать это:

CGSize scrollableSize = CGSizeMake(320, myScrollableHeight);
[myScrollView setContentSize:scrollableSize];

Затем он UIScrollViewбудет прокручиваться только по вертикали, потому что он уже может отображать все по горизонтали.


6
Здравствуй. Это решение отлично работает! Спасибо за это. Я попытался установить статическую ширину на 0. Для меня это тоже работает. Не знаю, могут ли быть побочные эффекты позже. Но если вы не знаете размер (т.е. универсальный код для iPhone и iPad), это отлично работает!
— JackPearse

5
Я думаю, что лучше сделать CGSizeMake (0, myScrollableHeight), поэтому горизонтальная прокрутка отключена, даже если отображались не все подпредставления.
— LightNight

NB. Установка одного из измерений на 0 при использовании разбиения по страницам приведет к тому, что VoiceOver объявит номер страницы как «страница 1 из 1» независимо от правильного значения
— josef

1
Вместо жестко заданной ширины 320, мы можем передать ее так: CGSize scrollableSize = CGSizeMake (self.scrollview.frame.size.width, myScrollableHeight); [myScrollView setContentSize: scrollableSize];
— Mohit kumar

91

ОБНОВЛЕНО: (после того, как @EranMarom указал на свой комментарий)

Вы можете остановить горизонтальную или вертикальную прокрутку в ScrollViewDelegateметоде. Вот как,

Останавливает горизонтальную прокрутку:

Если вы хотите прокручивать по горизонтали, вам нужно увеличить contentOffset.x. Предотвращение остановки прокрутки в горизонтальном направлении.

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    sender.contentOffset.x = 0.0
}

Останавливает вертикальную прокрутку:

Если вы хотите прокрутить по вертикали, вам нужно увеличить contentOffset.y. Предотвращение остановки прокрутки в вертикальном направлении.

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    sender.contentOffset.y = 0.0
}

Приведенный выше код предотвращает изменения в xи yиз scrollview contentOffsetи это приводит к остановить прокрутку в scrollViewDidScroll:методе.


1
Я подумываю о голосовании против, потому что этот ответ не объясняет, что вы только что дали код, и все. Такой ответ не очень хороший. Хороший ответ объясняется сам собой, в то время как опытные разработчики могут понять, что новые разработчики могут не понимать, что здесь происходит. Еще не проголосовано, так как дает шанс на улучшение.
— Popeye

14
Это своего рода взлом, но он работал, когда все остальное не помогло. Так что +1, но используйте только в крайнем случае.
— i_am_jorf

5
Я также использую этот метод делегата, но я заменяю тело однострочным, например: scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y);для отключения горизонтальной прокрутки. Я считаю его более читаемым, он меньше по размеру, и нет смысла проводить тест на ноль, потому что практически нет накладных расходов на код, который запускается так редко (то есть несколько десятков раз в секунду максимум).
— Echelon

потому что вы меняете contentOffset после «didscroll», а не как до «willscroll», и это решение молотка, но я сам не голосовал против, потому что 18 голосов за, а ответ - 75, так что отрицать не стоит
— LolaRun

2
Еще проще использовать, scrollView.contentOffset.y = 0.0чтобы остановить вертикальную прокрутку и scrollView.contentOffset.x = 0.0остановить горизонтальную прокрутку в scrollViewDidScroll()функции делегата. Однако я считаю, что проверка scrollView.contentSizeравенства scrollView.frame.size- лучшее (правильное) решение. См. Ответ @danbeaulieu.
— emem

11

с iOS7 использовать

self.automaticallyAdjustsScrollViewInsets = NO;

// и создадим вам скроллер с 3 страницами

    self.pageView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    [self.pageView setContentSize:CGSizeMake(self.view.frame.size.width*3, self.view.frame.size.height)];
    [self.pageView setShowsVerticalScrollIndicator:NO];
    [self.pageView setPagingEnabled:YES];
    [self.view addSubview:self.pageView];

Я не думаю, что это отключит поведение прокрутки в scrollview. Это??
— Динеш Раджа

self.collectionView.pagingEnabled = YES;помогли решить проблему с плавной прокруткой (не перетаскиванием). Проблема заключалась в методе scrollViewWillEndDragging:- targetContentOffset был таким же, как scrollView.contentOffset, и логика обнаружения страницы не работает должным образом.
— sig

11

Быстрое решение

Создайте два выхода, один для вашего представления и один для представления прокрутки:

@IBOutlet weak var myView: UIView!
@IBOutlet weak var scrollView: UIScrollView!

Затем в вашем viewDidLayoutSubviews вы можете добавить следующий код:

let scrollSize = CGSize(width: myView.frame.size.width, 
                        height: myView.frame.size.height)
scrollView.contentSize = scrollSize

Мы собрали высоту и ширину представления и установили соответствующий размер содержимого scrollViews. Это остановит вашу прокрутку от горизонтальной прокрутки.


Еще мысли:

CGSizeMake принимает ширину и высоту с помощью CGFloats. Возможно, вам потребуется использовать существующую высоту UIScrollViews для второго параметра. Это выглядело бы так:

let scrollSize = CGSize(width: myView.frame.size.width, 
                        height: scrollView.contentSize.height)

Что делать, если вы не знаете высоту или ширину (универсальное устройство)? @danbeaulieu
— Лукесиви

@lukesIvi myView.frame.width динамически извлекает ширину из IBOutlet myView.
— Dan Beaulieu

4

В моем случае с Swift 4.2 вы можете использовать:

Отключить вертикальную прокрутку:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.y = 0.0
}

Отключить горизонтальную прокрутку:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.x = 0.0
}

3

Вы можете выбрать вид, а затем Attributes Inspectorснять флажок User Interaction Enabled.


3

В моем случае ширина contentView была больше ширины UIScrollView, и это было причиной нежелательной горизонтальной прокрутки. Я решил это, установив ширину contentView равной ширине UIScrollView.

Надеюсь, это кому-то поможет


@Nostradamus рад помочь
— Галфам Хан

0

У меня был tableview contentInset, установленный в viewDidLoad (как показано ниже), что вызывает горизонтальную прокрутку

self.tableView.contentInset = UIEdgeInsetsMake(0, 30, 0, 0);

Проверьте, есть ли какой-либо tableview contentInset, установленный по разным причинам, и отключите его


0

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

Однако в другом потоке (не уверен, где) кто-то предположил, что использование отрицательного ограничения для UIScrollView сработало для него.

Поэтому я пробовал различные комбинации ограничений с противоречивыми результатами. Что в конечном итоге сработало для меня, так это добавить ведущие и конечные ограничения -32 к просмотру прокрутки и добавить (невидимое) текстовое представление шириной 320 (и по центру).


0

Попробуй это:

CGSize scrollSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, scrollHeight);
[scrollView setContentSize: scrollSize];

0

Отключите горизонтальную прокрутку, переопределив contentOffsetсвойство в подклассе.

override var contentOffset: CGPoint {
  get {
    return super.contentOffset
  }
  set {
    super.contentOffset = CGPoint(x: 0, y: newValue.y)
  }
}

0

В iOS 11 добавлено новое свойство UIScrollView

var contentLayoutGuide: UILayoutGuide

В документации указано, что вы:

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

Наряду с другими ограничениями Autolayout , которые могут быть добавляющими вы хотите ограничить widthAnchorиз UIScrollView«с contentLayoutGuideтаким же размером , как„кадр“. Вы можете использовать frameLayoutGuideширину (также введенную в iOS 11) или любую внешнюю ширину (например, вашу superView.)

пример:

NSLayoutConstraint.activate([
  scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: self.widthAnchor)
])

Документация: https://developer.apple.com/documentation/uikit/uiscrollview/2865870-contentlayoutguide



Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.