Как отключить горизонтальную прокрутку 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.