UIScrollView не прокручивается

128

У меня есть a, UIScrollViewкоторый содержит много UIImageViews, UILabels и т.д ... метки намного длиннее UIScrollView, но когда я запускаю приложение, я не могу щелкнуть и прокрутить вниз ...

Почему это могло быть?

Спасибо

отметка
источник
Новое 26
Дики Сингх

Ответы:

169

Всегда полезно показать полный рабочий фрагмент кода:

// in viewDidLoad (if using Autolayout check note below):

UIScrollView *myScrollView;
UIView *contentView;
// scrollview won't scroll unless content size explicitly set

[myScrollView addSubview:contentView];//if the contentView is not already inside your scrollview in your xib/StoryBoard doc

myScrollView.contentSize = contentView.frame.size; //sets ScrollView content size

Swift 4.0

let myScrollView
let contentView

// scrollview won't scroll unless content size explicitly set

myScrollView.addSubview(contentView)//if the contentView is not already inside your scrollview in your xib/StoryBoard doc

myScrollView.contentSize = contentView.frame.size //sets ScrollView content size

Я не нашел способа установить contentSize в IB (начиная с Xcode 5.0) .

Примечание. Если вы используете Autolayout, лучше всего разместить этот код внутри -(void)viewDidLayoutSubviewsметода.

Богатырь
источник
12
Не забудьте установить myScrollView.delegate = selfТАКЖЕ, если это все еще не работает, ответ ниже содержит ОТЛИЧНЫЙ совет (перейдите на свой xib / StoryBoard и убедитесь, что «AutoLayout» отключен). Подсказка: вы также можете включить его <UIScrollViewDelegate>в свой .h файл, если хотите делать такие вещи, как программная прокрутка UIScrollView.
Альберт Реншоу
1
@AlbertRenshaw, вы должны были добавить ответ, чтобы я мог дать вам +1 :) Проблема с AutoLayout… сводила меня с ума примерно на 4 часа.
логиксолог 02
2
Ввод кода viewDidLayoutSubviewsзаставил меня работать.
Амр Лотфи
Для меня проблема заключалась в том, что не нужно было прокручивать, так как все умещалось на экране.
Дэниел Спрингер,
122

Если вы не можете прокрутить вид даже после того, как вы установили contentSize правильно, убедитесь , что вы снимите «Использовать AutoLayout» в Interface Builder -> File Inspector.

user1539652
источник
165
В качестве альтернативы вы можете установить contentSize в viewDidLayoutSubviews : , и он будет применен после завершения автоматического размещения.
Крис Васселли
2
@ "Крис Васселли" любит мою проблему .. GR8 .. :-)
Ayaz
3
Комментарий Криса должен быть отдельным ответом!
ninjaneer
1
Спасибо вам огромное, Крис Васселли! При включенном автоматическом макете он не будет работать в viewDidLoad, но он работает с viewDidLayoutSubviews!
Romain
1
Ого, я никогда раньше не замечал всех этих комментариев! Рад, что смог помочь многим из вас! Я только что опубликовал отдельный ответ, так что, надеюсь, его будет легче найти.
Крис Васселли
68

Вам необходимо установить contentSizeсвойство представления прокрутки, чтобы оно правильно прокручивалось.

Если вы используете autolayout, вам необходимо установить contentSizeв viewDidLayoutSubviewsдля того , чтобы применять его после autolayout завершается.

Код может выглядеть так:

-(void)viewDidLayoutSubviews
{
    // The scrollview needs to know the content size for it to work correctly
    self.scrollView.contentSize = CGSizeMake(
        self.scrollContent.frame.size.width,
        self.scrollContent.frame.size.height + 300
    );
}
Крис Васселли
источник
Большое спасибо. Это сработало, потому что по какой-то причине, даже когда я устанавливаю значение contentSizeна размер contentView, размер scrollView и contentView, кажется, устанавливается одинаковым. Но установив для высоты contentSizeзначение больше, чем высота contentView, это сработало.
Скайуокер,
viewDidLayoutSubviewsможет вызываться несколько раз в течение жизненного цикла, поэтому вы рискуете увеличить высоту больше, чем ожидалось.
anon_nerd
@anon_nerd просто проверьте, был ли он уже вызван, и только добавьте высоту, если нет
Дэниел Спрингер,
45

Ответ правильный - для прокрутки необходимо установить размер содержимого.

Если вы используете построитель интерфейсов, то простой способ сделать это - использовать атрибуты времени выполнения, определенные пользователем. Например:

введите описание изображения здесь

Джаспер Блюз
источник
это ничего не сделало для меня.
coolcool1994
4
К сожалению, на картинке изображено {0, 0}, но вы, конечно, должны ввести достаточно большие числа. , этот подход будет работать только для простых представлений, когда вы заранее знаете размер содержимого. , , (на самом деле, для сложных представлений я все равно рекомендую чистый код).
Jasper Blues
Намного менее хакерский, чем программный. Спасибо!
Джейк Стоффлер,
1
@JakeStoeffler добро пожаловать! :) При использовании ИБ я люблю хранить там весь конфиг (не фрагментированный). Но когда все становится сложным (многоразовые виджеты представления; адаптеры моделей, манипуляции со слоями; CAAnimations и т. Д.), Я предпочитаю полностью программные представления. , , более бегло.
Jasper Blues
Я пробовал это, работает, когда появляется представление, но при изменении ориентации contentSize, определенный на экране выше, игнорируется, и в моем журнале говорится, что contentSize установлен на 0,0. Есть идеи, как это исправить?
Shoogle
40

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

self.scrollView.contentSize = CGSizeMake(2000, 2000);

Вместо 2000 вы можете поставить свои большие числа. И если это работает, это означает, что размер вашего контента недостаточно велик при изменении размера.

Для работы режима прокрутки делегат не требуется.

Денис Кутлубаев
источник
2
Genius - такой простой способ проверить, что происходит. Огромное спасибо!
The Crazy Chimp
13

Убедитесь, что для свойства contentSize представления прокрутки установлен правильный размер (т. Е. Достаточно большой, чтобы вместить весь ваш контент).

Бен Готтлиб
источник
1
я должен делать это программно? или можно в ИБ?
Марк
Если вы используете IB, вы можете установить его оттуда - см. Ниже. , (Ответ отдельный, поэтому я могу включить фото).
Jasper Blues
7

Снимите флажок "Использовать автопрокладку" для меня.

Среда: xCode 5.0.2 Раскадровки ios7

Гаурав Кумкар
источник
5

В моем случае мне пришлось установить delaysContentTouchesзначение true, потому что все объекты внутри scrollView захватывали события касания и обрабатывали сами себя, а не позволяли самому scrollView обрабатывать их.

devios1
источник
У меня такая же проблема. Проблема для меня в том, что, установив для параметра delayaysContentTouches значение true, вы получите более низкое качество рисунков с помощью яблочного карандаша. Но это
крайний
4

Установить contentSizeсвойство UIScrollviewв ViewDidLayoutSubviewsметоде. Что-то вроде этого

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    scrollView.contentSize = CGSizeMake(view.frame.size.width, view.frame.size.height)
}
Винаяк Пармар
источник
3

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

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

добро пожаловать :)

Abo3atef
источник
3

Одно небольшое дополнение, все вышеперечисленное - это фактические причины, по которым ваше представление прокрутки может не прокручиваться, но иногда бездумно это может быть причиной, особенно когда scrollview добавляется через код, а не IB, вы могли добавить свои подпредставления в родительский вид, а не в scrollview это заставляет subview не прокручиваться

и держите размер содержимого установленным и больше, чем родительский фрейм представления (даааа !!)

Абхинав Сингх
источник
3

Я заставил это работать с первой попытки. С автоматическим макетом и всем остальным, без дополнительного кода. Затем представление коллекции превратилось в банан, вылетело во время выполнения, я не смог найти, что было не так, поэтому я удалил и воссоздал его (я использую Xcode 10 Beta 4. Это было похоже на ошибку), а затем прокрутка исчезла. Однако представление «Коллекция» снова заработало!

Много часов спустя .. вот что исправило для меня. У меня была такая раскладка:

UIView

  • Безопасный район
  • Прокрутка
    • Просмотр содержимого

Все дело в ограничениях. Безопасная зона определяется системой автоматически. В худшем случае удалите все ограничения для прокрутки и просмотра содержимого и не позволяйте IB сбрасывать / создавать их за вас. Сделайте их вручную, все работает.

  • Для прокрутки я сделал: Выровняйте трейлинг / верх по безопасной области. Равная ширина / высота для безопасной зоны .
  • Для представления содержимого я сделал: Выровнять Trailing / Leading / Top / Bottom по Superview (представление прокрутки)

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

Но как таковой это не сработало. Просмотр содержимого пропустил высоту. Я пробовал все, что мог, и единственное, что помогало, - это созданная с помощью элемента управления высота представления содержимого и перетаскивание представления содержимого… на себя . Это определило фиксированную высоту, значение которой было вычислено из размера контроллера представления (определенного как произвольная форма, длиннее, чем реальный дисплей, чтобы содержать все мои подпредставления), и, наконец, это снова сработало!

Мишель Далл'Агата
источник
Пожалуйста! Я точно знаю, как вы себя чувствовали .. ;-)
Мишель Далл'Агата
Thaaaaks, я потратил много часов, и это решило мою проблему
Andoni Da Silva
3

если вы получаете сообщение (IOS8 / swift), viewDidLayoutSubviewsкоторого не существует, используйте вместо этого следующее

override func viewDidAppear(animated: Bool)

Это исправило это для меня

Джейсон Джи
источник
2

То, о чем раньше не упоминалось!

Убедитесь, что ваша розетка правильно подключена к scrollView! На нем должен быть закрашенный круг, но даже если вы закрасили круг, scrollView может не быть подключен - так что дважды проверьте! Наведите указатель мыши на кружок и посмотрите, выделится ли фактическая прокрутка! (Это был случай для меня)

//Connect below well to the scrollView in the storyBoard
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
coolcool1994
источник
2

В большинстве случаев код верен, если вы следовали руководству, но многие новички не знают, что scrollView НЕ будет нормально прокручивать симулятор. Предполагается, что прокрутка выполняется только тогда, когда вы нажимаете на коврик для мыши и одновременно прокручиваете. Многие опытные пользователи XCode / Swift / Obj-C так привыкли к этому, что не знают, как это могло быть упущено новичками. Чао :-)

@IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(scrollView)
    // Do any additional setup after the view
}

override func viewWillLayoutSubviews(){
    super.viewWillLayoutSubviews()
    scrollView.contentSize = CGSize(width: 375, height: 800)
}

Этот код будет работать отлично, пока вы будете делать то, что я сказал выше.

flo527
источник
1

Если ни одно из других решений не работает для вас, дважды проверьте, действительно ли ваше представление прокрутки UIScrollView в Interface Builder.

В какой-то момент за последние несколько дней мой UIScrollView тип спонтанно изменился на a UIView, хотя его класс сказал UIScrollViewв инспекторе. я используюXcode 5.1 (5B130a) .

Вы можете создать новое представление прокрутки и скопировать измерения, настройки и ограничения из старого представления, либо вы можете вручную изменить вид на a UIScrollViewвxib файле. Я провел сравнение и обнаружил следующие отличия:

Оригинал:

<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" directionalLockEnabled="YES" bounces="NO" pagingEnabled="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Wsk-WB-LMH">
...
</scrollView>

После спонтанной смены типа:

<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" customClass="UIScrollView" id="qRn-TP-cXd">
...
</view>

Поэтому я заменил <view>строку своей оригинальной<scrollView> строкой.

Я также заменил закрывающий тег представления </view>на</scrollView> .

Убедитесь, что id такой же, как у текущего представления, в этом случае: id = "qRn-TP-cXd".

Мне также пришлось очистить xib из кеша Xcode, удалив производные данные приложения:

  • Xcode->Window->Organizer->Projects, выберите свой проект, в строке "Производные данные" нажмите Удалить ...

Или при использовании устройства:

  • Xcode->Window->Organizer->Device, выберите свое устройство-> Приложения, выберите приложение, нажмите (-)

Теперь очистите проект и удалите приложение с симулятора / устройства:

  • Xcode->Product->Clean
  • iOS Simulator/device->pressи удерживайте app->click(X), чтобы удалить его.

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

PS Мне не нужно было устанавливать размер содержимого прокрутки viewDidLayoutSubviewsили отключать автоматическую компоновку, но YMMV.

Зак Моррис
источник
1

Если ваше scrollViewпредставление containerViewнекоторого типа, убедитесь, что оно scrollViewнаходится в пределах фрейма или границ containerView. У меня было то, containerView.clipsToBounds = NOчто все еще позволяло мне видеть scrollView, но поскольку оно scrollViewне было в границах, containerViewоно не обнаруживало сенсорных событий.

Например:

containerView.frame = CGRectMake(0, 0, 200, 200);
scrollView.frame = CGRectMake(0, 200, 200, 200);
[containerView addSubview:scrollView];
scrollView.userInteractionEnabled = YES;

Вы сможете увидеть scrollView, но он не получит взаимодействия с пользователем.

Чейз Робертс
источник
1

добавление следующего кода viewDidLayoutSubviewsсработало для меня с Autolayout. Перепробовав все ответы:

- (void)viewDidLayoutSubviews
{
    self.activationScrollView.contentSize = CGSizeMake(IPHONE_SCREEN_WIDTH, 620);

}

//set the height of content size as required
Умный iPhone
источник
1

Добавьте UIScrollViewDelegateи добавив следующий код в viewDidAppearметод, исправивший это для меня.

@interface testScrollViewController () <UIScrollViewDelegate>

-(void)viewDidAppear:(BOOL)animated {
    self.scrollView.delegate = self;
    self.scrollView.scrollEnabled = YES;
    self.scrollView.contentSize = CGSizeMake(375, 800);
}
Трианна Браннон
источник
1

Моя проблема была решена:

  1. установка contentSize в scrollView на большую высоту
  2. НО также мне пришлось исправить верхние и / или нижние ограничения для представлений в scrollView, что означало, что индикаторы прокрутки отображались на экране, но содержимое не прокручивалось.

Как только я удалил верхние и / или нижние ограничения, привязанные к безопасной области и / или супервизору, представления внутри scrollView могли снова прокручиваться и не оставались фиксированными в верхней или нижней части экрана!

Надеюсь, это избавит кого-то от многих часов боли с этой конкретной проблемой.

Генри Хелейн
источник
1

еще один забавный случай:

scrollview.superview.userInteractionEnabled должно быть истинным

Я потратил 2+ часа на погоню за этим, чтобы понять, что родительский элемент - это UIImageView, который, естественно, имеет userInteractionEnabled == false

Антон Тропашко
источник
0

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

Есть две вещи, которые не интуитивно понятны при настройке режима прокрутки с автоматическим размещением:

  1. Ограничения, которые вы устанавливаете в качестве поля между contentview и scrollview, не влияют на размер contentview. Это действительно маржа. И чтобы это работало, contentview должен иметь фиксированный размер.
  2. Уловка с фиксированным размером заключается в том, что вы можете установить ширину ContentView равной ширине родительского элемента scrollview. Просто выберите оба вида в дереве слева и добавьте ограничение равной ширины.

В этом суть статьи. Полное объяснение, включая иллюстрации, можно найти здесь.

Х. де Йонге
источник
@PredragManojlovic Как это может быть более общим, чем это? Это единственный способ заставить прокрутку работать должным образом, используя автоматическую компоновку.
Х. де Йонге
0

Я обнаружил, что с этой проблемой AutoLayout ... если я просто ViewControllerиспользую UIViewвместо UIScrollViewкласса ... тогда просто добавляю UIScrollViewсебя ... что он работает.

Брайан Райс
источник
0

У меня была такая же проблема в IB.

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

Чтобы scrollView прокручивалась только в горизонтальном направлении, сделайте ограничение с помощью scrollView centerY = ContainerView centerY

и чтобы сделать его вертикально прокручиваемым, сделайте scrollView centerX = ContainerView centerX

Nandu
источник