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

86

В IB есть возможность снять флажок с вертикальной прокрутки при просмотре прокрутки, но, похоже, это не работает.

Как можно настроить scrollview для прокрутки только по горизонтали, а не по вертикали в коде, а не в IB?

система
источник

Ответы:

121

Попробуйте установить высоту contentSize равной высоте scrollView. Затем следует отключить вертикальную прокрутку, потому что вертикально прокручивать нечего.

scrollView.contentSize = CGSizeMake(scrollView.contentSize.width,scrollView.frame.size.height);
pt2ph8
источник
Вы только что сэкономили мне много времени на отладку этой странной проблемы. Благодаря!
jpm
2
@fabb как узнать, когда фрейм изменен?
Сэм
138

начиная с iOS7:

сначала: ширина размера содержимого должна быть равна ширине вашего прокрутки

второй: в вашем initWithNibName:

self.automaticallyAdjustsScrollViewInsets = NO;

Это оно.

Мирко Бруннер
источник
Замечательное решение. Работал как шарм. Повлияет ли это на размер остальных представлений в моем ViewController? (Кнопки, ярлыки ..) Я имею в виду, что "self" в моем случае является UIViewController
voghDev
@voghDev нет, это не влияет на подпредставления в вашем scrollview.
Мирко Бруннер
Компания Amazing добавила это к методу viewdidload на моих контроллерах представления, у которых были проблемы.
StackRunner
если вы используете navigationController и ваш scrollview находится за заголовком navigationBar, как мое использование в методе viewDidLoad. Это решает.
EFE
1
Вы можете добиться того же в настройках раскадровки напрямую, без какой-либо строчки кода. Просто выберите контроллер представления прокрутки и снимите флажок «Настроить вставки представления прокрутки» в инспекторе атрибутов.
Morpheus78,
49

да, ответ pt2ph8 правильный,

но если по какой-то странной причине ваш contentSize должен быть выше, чем UIScrollView, вы можете отключить вертикальную прокрутку, реализовав метод протокола UIScrollView

 -(void)scrollViewDidScroll:(UIScrollView *)aScrollView;

просто добавьте это в свой UIViewController

float oldY; // here or better in .h interface

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
    [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x, oldY)];
    // or if you are sure you wanna it always on top:
    // [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x, 0)];
}

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

Мероникс
источник
6
Бог! НЕ объявляйте переменную oldY в файле .m, как показано в float oldY;приведенном выше коде. Это символ переменной в стиле C для каждого приложения, переменная ДОЛЖНА быть объявлена ​​как член экземпляра класса контроллера.
Итачи
21

Включите следующий метод

-(void)viewDidLayoutSubviews{
    self.automaticallyAdjustsScrollViewInsets = NO;
}

и установите ширину размера содержимого представления прокрутки, равную ширине представления прокрутки.

Фебин П
источник
1
Это также можно сделать в Storyboard, выбрав View Controller и
сняв
1
Мне это не нравится, потому что он устанавливает его для всех видов прокрутки ... Желаю, чтобы вы могли быть конкретными для одного вида прокрутки на диаграмме без создания нового класса ScrollView и т. Д.
visc
20

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

Чтобы отключить вертикальную прокрутку

scrollView.contentSize = CGSizeMake(scrollView.contentSize.width,0);

Чтобы отключить горизонтальную прокрутку

scrollView.contentSize = CGSizeMake(0,scrollView.contentSize.height);
Мани
источник
1
Это установит для contentSize представления значение 0 на установленной вами оси. ContentSize относится к размеру содержимого, поэтому мы хотим передать высоту экрана, чтобы отключить вертикальную прокрутку за пределами этого кадра. решение, отмеченное как правильное, является правильным.
system
У меня это сработало. установка высоты в качестве высоты contentSize по-прежнему заставила меня вертикальную прокрутку.
KoreanXcodeWorker
1
У меня это не сработало. Также пробовал self.automaticallyAdjustsScrollViewInsets
StackRunner
Это оно! Установка высоты прокрутки у меня не сработала, но это
сработало
18

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

Может и есть люди с этой проблемой.

Болонн
источник
Вы спасли меня. Мой размер содержимого и рамка были такими же, и я не мог понять, что случилось. Огромное спасибо!!
yuf
2
Ваш ответ: почему я люблю stackoverflow! :-) Святой дым ... это сводило меня с ума! Ты прав. Это эффект отскока. Мне нужен эффект отскока, но не тогда, когда нет необходимости прокручивать, поэтому я постараюсь отключить / повторно включить этот эффект сейчас в коде в зависимости от того, нужна ли прокрутка.
Эрик ван дер Нейт,
2
Хорошо, очень легко включить / отключить отказы в UIScrollView во время выполнения. В моем случае меня заботит только высота содержимого прокрутки, и это помогло: self.scrollView.bounces = (BOOL) (self.scrollView.contentSize.height> self.scrollView.frame.size.height);
Эрик ван дер Нейт
12
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
    [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x,0)];

}

вы должны были подтвердить UIScrollViewDelegate

aScrollView.delegate = self;

источник
4

Просто установите y, чтобы он всегда был сверху. Необходимо соответствовать UIScrollViewDelegate

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

Это сохранит эффект замедления / ускорения прокрутки.

Мануэльсантос
источник
4

В iOS 11 не забудьте добавить следующее, если вы заинтересованы в создании прокрутки, которая придерживается границ экрана, а не безопасной области:

if (@available(iOS 11.0, *)) {
    [self.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
}
Майкл
источник
1
после всего. тысячу раз спасибо, сэр! Ты спас мне день
ha100
1

Из iOS11 можно использовать следующее свойство

let frameLayoutGuide: UILayoutGuide

Если установить ограничения для frameLayoutGuide.topAnchor и frameLayoutGuide.bottomAnchor к тому же якорей некоторых подвид вашего Scrollview то вертикальная полоса прокрутки будет отключена и высота Scrollview будет равна высоте ее подвид.

Malex
источник
1

Наиболее очевидное решение - запретить изменение координаты Y в вашем подклассе.

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

Это единственное подходящее решение в ситуациях, когда:

  1. Вам не разрешено или вы просто не хотите использовать делегат.
  2. Высота вашего контента больше высоты контейнера
iWheelBuy
источник
1
Это лучший ответ! Следует выбрать как решение! Спасибо, дружище, ты спас мне день!
imike
@imike моим любимым решением является использование swizzling (: Проверьте github.com/iwheelbuy/UIPanGestureRecognizerDirection репо
iWheelBuy
0

Многие ответы включают установку значения contentOffset0. У меня был случай, когда я хотел, чтобы представление внутри scrollView было центрировано. Это сработало для меня:

public func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.y = -scrollView.contentInset.top
}
regina_fallangi
источник