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

Кодер221
источник
3

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

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

Гульфам Хан
источник
@Nostradamus рад помочь
Галфам Хан
0

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

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

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

Найшта
источник
0

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

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

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

PatriciaW
источник
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)
  }
}
iWheelBuy
источник
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

JMFR
источник
-1

Как только я сделал это, заменив UIScrollView на UITableView только с одной ячейкой, все заработало.

Хола Сой Эду Фелиз Навидад
источник
1
Извините, это не ответ на вопрос.
Дэвид
-1

Используйте эту единственную строку.

self.automaticallyAdjustsScrollViewInsets = NO;

Картиккк
источник