Swift UIScrollView - правильная реализация только для вертикальной прокрутки

Заранее прошу прощения, поскольку я бы сказал, что я новичок в программировании iOS.

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

Я использую Storyboard для рисования представлений с помощью AutoLayout.

Вот скриншот моего UIViewController с UIScrollView:

enter image description hereenter image description here

Затем я меняю ярлык на такой большой текст, как

override func viewDidLoad() {
    super.viewDidLoad()

    self.label1Label.text = "Seize jours après la chute du président Blaise Compaoré, le Burkina Faso a un nouveau chef d'EtatA l'issue d'ultimes tractions, civils et militaires se sont accordés, lundi 17 novembre, sur le nom du diplomate Michel KafandoSeize jours après la chute du président Blaise Compaoré, le Burkina Faso a un nouveau chef d'EtatA l'issue d'ultimes tractions, civils et militaires se sont accordés, lundi 17 novembre, sur le nom du diplomate Michel Kafando"
    self.label1Label.numberOfLines = 0
    self.label1Label.sizeToFit()

Моя проблема в том, что если я не устанавливаю вручную ширину для моего contentView (внутри UIScrollView), прокрутка горизонтальная, а не вертикальная. (Посмотрите снимок экрана ниже):

enter image description here

Я попытался установить contentSize, как я видел во многих сообщениях Google, но безуспешно:

self.scrollView.contentSize = CGSizeMake(400.0, 600.0)

Если я задаю ширину вручную для моего содержимого (i.e : 320pts), прокрутка будет вертикальной (ХОРОШО), но тогда, в зависимости от размера iphone, она не будет покрывать всю ширину экрана, как показано ниже Снимок экрана:

enter image description here

Вопрос: в чем правильная реализация использовать UIScrollView, чтобы иметь contentView, которые учитывают ограничение автоопределения (full screen : 0top - 0bottom - 0left - 0right), а прокрутка - только вертикальная.

Большое спасибо за вашу помощь!

Ответ 1

Майк Woelmer показывает, как это сделать правильно с Interface Builder в блоке Atomic Object.

http://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/

У меня также есть собственный код (без реализации раскадровки) на github.

https://github.com/nadthevlad/AutolayotScrollview

Вы не хотите устанавливать высоту или ширину вашего контента или представлений. Вместо этого вы хотите использовать контакты Autolayouts и ограничения для определения поведения прокрутки.

  • Создайте свой scrollView UIScrollView *.

  • Вы хотите создать один UIView * contentView, в который будут помещены остальные элементы вашего представления.

    [self.view addSubview:scrollView];
    [scrollView addSubview:contentView];
    [contentView addSubview:_label1];
    [contentView addSubview:_label2];
    [contentView addSubview:_label3];
    [contentView addSubview:_label4];
    [contentView addSubview:_label5];
    [contentView addSubview:_label6];
    
  • Подсоедините 4 края scrollView к 4 краям self.view

  • Зажмите верхний и нижний края contentView в верхней и нижней части scrollView.

  • Это сложная часть. Чтобы установить горизонтальный размер, вы хотите, чтобы ведущие (правые) и конечные (левые) края содержимогоView были привязаны к главному и заднему краям self.view вместо scrollView. Несмотря на то, что contenView является дополнительным представлением scrollView, его горизонтальные ограничения будут доступны за пределами scrollView и подключаться к self.view.

  • Подключите любые другие элементы вида к contentView, как обычно.

Ответ 2

Трюк, позволяющий прокрутке UIScrollView только в одном направлении, заключается в том, чтобы сделать размер содержимого UIScrollView для ограниченного размера таким же, как размер кадра UIScrollView в том же измерении. Поэтому в этом случае scrollview.contentSize.width должен равняться scrollview.frame.size.width.

С учетом этого попробуйте следующее:

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

  • Добавьте следующий код в контроллер вида:

    override func viewWillLayoutSubviews()
    {
        super.viewWillLayoutSubviews();
        self.scrollView.contentSize.height = 3000; // Or whatever you want it to be.
    }
    

Лично я не являюсь поклонником Auto Layout. Если вы заинтересованы в попытке сделать это без автоматического макета, т.е. просто с кодом вместо ограничений - вы можете отключить автоматическую компоновку для представления контроллера вида и изменить свой метод viewWillLayoutSubviews, чтобы выглядеть так:

override func viewWillLayoutSubviews()
{
    super.viewWillLayoutSubviews();

    self.scrollView.frame = self.view.bounds; // Instead of using auto layout
    self.scrollView.contentSize.height = 3000; // Or whatever you want it to be.
}

Ответ 3

Это, как я всегда делаю это для прокрутки по вертикали от раскадровки с ограничениями:

1-перетащить viewcontroller

2-перетащите прокрутку в главном окне контроллера с ограничениями L = 0, T = 0, T = 0 и B = 0 на его супервизор (основной вид контроллера).

3-перетащите UIVIew в представление прокрутки, чтобы работать как его просмотр содержимого с ограничениями L-0, T = 0, T = 0, B = 0 на его супервизор (прокрутка)

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

4 - для остановки горизонтальной прокрутки сделайте просмотр содержимого равным ширине для scrollview с ограничением.

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

6-добавить элементы управления в представлении содержимого до завершения.

7 - и самое главное удалить ограничение, которое вы указали в точке 5 высоты представления содержимого, и вместо этого сделать ограничение от элемента управления в нижней части содержимого, чтобы иметь нижнее выравнивание к нему. Это помогает в создании высоты представления содержимого, начиная с первого элемента управления сверху и снизу до последнего элемента управления (все зависит от этого шага).

8-just run и результаты должны быть такими, как ожидалось, иначе сообщите мне.

Надеюсь, это поможет!

Ответ 4

Я использую эту реализацию только для горизонтальных/вертикальных прокрутки, хотя она находится в Objective-C, я попытаюсь объяснить логику, если вам что-то непонятно.

//Getting iDevice screen width
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;

//Setting the right content size - only height is being calculated depenging on content.
CGSize contentSize = CGSizeMake(screenWidth, HEIGHT_OF_YOUR_CONTENT);
self.scrollView.contentSize = contentSize;

Теперь ширина свойства contentSize прокрутки будет привязана к фактической ширине экрана устройства, поэтому прокрутка будет прокручиваться только в вертикальном направлении.

Ответ 5

Благодаря @NadtheVlad, я наконец увидел свет. Некоторое дополнительное упражнение научило меня, что contentView просто нужно прикрепить к scrollView Top, Bottom and Width. Не нужно ссылаться на self.view.

С EasyPeasy это просто:

scrollView <- Edges()
contentView <- [Top(), Bottom(), Width().like(scrollView)]

Ответ 6

Вы можете определить ScrollView как обычно и ограничить свойства ScrollView как обычно

        let scrollView = UIScrollView()
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.backgroundColor = .white
    self.view.addSubview(scrollView)

    scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0.0).isActive = true
    scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0.0).isActive = true
    scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0.0).isActive = true
    scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0.0).isActive = true

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

myLabel.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: -10.0).isActive = true

Вы должны использовать

myLabel.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -10.0).isActive = true

Эта вторая строка не даст этому виду вызвать горизонтальную прокрутку. Сделайте это со всеми вашими подпредставлениями, и вы не будете прокручивать по горизонтали. (Он будет по-прежнему прокручиваться вертикально, как и планировалось.)

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

labelX.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -10.0).isActive = true