Подтвердить что ты не робот

UIScrollView contentSize не работает

Я положил UIScrollView в свой nib view и связал его с свойством IBOutlet.

Теперь, когда я делаю это в своем методе viewDidLoad, он, кажется, не влияет на contentSize:

self.sv.backgroundColor = [UIColor yellowColor]; // this works
CGSize size =  CGSizeMake(1000.0, 1000.0); 
[self.sv setContentSize:size]; // this does not

Он ведет себя так, как будто contentSize совпадает с фреймом. Что происходит? Это начало работать, когда я отключил AutoLayout. Почему?

4b9b3361

Ответ 1

У меня была та же проблема. Автоматический макет для UIScrollView испорчен.

Работайте: поместите все в UIScrollView в другой UIView и поставьте UIView как единственный дочерний элемент UIScrollView. Затем вы можете использовать автоматический макет.

Если вещи ближе к концу испорчены (конец любого направления ваших свитков UIScrollView), измените ограничение в конце, чтобы иметь самый низкий возможный приоритет.

Ответ 2

Я попробовал viewWillLayoutSubviews для обновления scrollView contentSize, это сработало для меня.

- (void)viewDidLayoutSubviews
{
  [self.bgScrollView setContentSize:CGSizeMake(320, self.view.frame.size.height* 1.5)];
}

Apple Doc

-(void)viewDidLayoutSubviews

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

Обсуждение

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

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

Ответ 3

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

Ответ 4

Здесь есть две проблемы. (1) viewDidLoad слишком скоро; вам нужно подождать, пока не произойдет макетирование. (2) Если вы хотите использовать автозапуск с прокруткой, который исходит от ниба, то либо вы должны использовать ограничения, чтобы полностью описать размер contentSize (а затем вы не устанавливаете contentSize в коде вообще), или, если вы хотите установить его в коде, вы должны запретить ограничения на subviews scrollview от диктовки contentSize. Похоже, вы хотели бы сделать последнее. Для этого вам нужен UIView, который выступает в качестве единственного поднабора верхнего уровня прокрутки, а в коде вы должны установить, чтобы он не использовал автозапуск, включив его autoresizingMask и удалив другие внешние ограничения. Я показываю пример того, как это сделать, здесь:

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/ch20p573scrollViewAutoLayout/ch20p573scrollViewAutoLayout/ViewController.m

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

Ответ 5

СУПЕР простой способ использования AutoLayout с UIScrollViews внутри Interface Builder:

Шаг 1: Создайте UIScrollView

Шаг 2: Создайте UIView, который является дочерним элементом вашего вида прокрутки, например:

-UIScrollView
---UIView
-----Your other content

(Мы назовем это contentView).

Шаг 3: В инспекторе размеров дайте этому представлению высоту и ширину (скажем, 320x700).

tsfiH.png

Шаг 4 (с использованием AutoLayout): Создайте однозначные ограничения из вашего contentView в его супервизор (UIScrollView): соедините 4 ребра (верхний, верхний, конечный, нижний), затем дайте ему определенную ширину и высоту, которые вы хотите прокрутить.

Например: если ваш просмотр прокрутки охватывает весь экран, вы можете указать, что ваш контент имеет ширину [ширина устройства] и высоту 600; он затем установит размер содержимого UIScrollView для соответствия.

ИЛИ

Шаг 4 (не используя AutoLayout): Подключите оба этих новых элемента управления к вашему контроллеру просмотра с помощью IB (ctrl + перетащите из каждого элемента управления в контроллер вида .h @implementation). Предположим, что каждая из них называется scrollView и contentView, соответственно. Он должен выглядеть следующим образом:

@interface YourViewController : UIViewController

@property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
@property (strong, nonatomic) IBOutlet UIView *contentView;

@end

Шаг 5 (не используя AutoLayout): В файле контроллера .h файл добавьте (фактически, переопределите) следующий метод:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    self.scrollView.contentSize = self.contentView.frame.size;
}

Ответ 6

Используйте этот код. ScrollView setContentSize должен вызываться как асинхронный в главном потоке.

Swift:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    DispatchQueue.main.async {
        var contentRect = CGRect.zero

        for view in self.scrollView.subviews {
           contentRect = contentRect.union(view.frame)
        }

        self.scrollView.contentSize = contentRect.size
    }
}

Цель C:

 - (void)viewDidLayoutSubviews {
     [super viewDidLayoutSubviews];

     dispatch_async(dispatch_get_main_queue(), ^ {
                        CGRect contentRect = CGRectZero;

                        for(UIView *view in scrollView.subviews)
                           contentRect = CGRectUnion(contentRect,view.frame);

                           scrollView.contentSize = contentRect.size;
                       });
}

Ответ 7

Вы можете использовать эти строки кода в своем *.m файле

- (void)viewDidLoad{
   [scroll setContentSize:CGSizeMake(320, 800)]   ;
   [scroll setScrollEnabled:TRUE];
   [scroll setShowsVerticalScrollIndicator:NO];
   [scroll setShowsHorizontalScrollIndicator:YES];
}    

для этого вам нужно взять свойство IBOutlet UIScrollView в ваш *.h файл следующим образом:

IBOutlet UIScrollView *scroll;

И подключите это от раскадровки.

Или

Вы можете использовать этот метод в своем *.m файле:

-(void)viewDidLayoutSubviews 
{
  [scroll setContentSize:CGSizeMake(320, self.view.frame.size.height* 1.5)];
   // this will pick height automatically from device height and multiply it with 1.5  
}

Это решение работает для меня в xcode-5, xcode-6, xcode-6.1, xcode-6.2

Ответ 8

Значение contentSize в viewDidAppear имеет решающее значение.

Но у меня также была вариация того, что работало на 3,5-дюймовом экране, и на 4-дюймовом экране. 4-дюймовый экран работал, а старший - нет. И iOS 7. Bizarre - это преуменьшение!

Ответ 9

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

 class MyScrollView:UIScrollView {

    var myContentSize:CGSize = CGSize.zero  // you must set this yourself 

    override func layoutSubviews() {
       super.layoutSubviews()
       contentSize = myContentSize
    }

 }

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

let scrollView = viewWithTag(90) as! MyScrollView      
scrollView.myContentSize = ...

Ответ 10

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

@interface MyView : UIScrollView {}
@end

@implementation MyView
- (void)setContentSize:(CGSize)aSize {
    if (aSize.height > 0)
        [super setContentSize:aSize];
}
@end

Ответ 11

Если вы используете AutoLayout, очень простой способ установить contentSize для UIScrollView - это просто добавить что-то вроде этого:

CGFloat contentWidth = YOUR_CONTENT_WIDTH;

NSLayoutConstraint *constraintWidth = 
 [NSLayoutConstraint constraintWithItem:self.scrollView 
                              attribute:NSLayoutAttributeTrailing 
                              relatedBy:NSLayoutRelationEqual 
                                 toItem:self.scrollView 
                              attribute:NSLayoutAttributeLeading 
                             multiplier:1 
                               constant:contentWidth];

[self.scrollView addConstraint:constraintWidth];

Ответ 12

Я использовал для настройки uiscrollview программно UNTIL Я наблюдал за следующим замечательным учебным пособием, шаг за шагом, как заставить uiscrollview и uiview работать: https://www.youtube.com/watch?v=PgeNPRBrB18

После просмотра видео вы начнете любить Interface Builder, я уверен.

Голосовать

Ответ 13

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

Я сделал то, что ответил yuf, как указано выше, как указано выше (я добавил представление содержимого в свой scrollview и установил ограничения, ведущие, конечные, верхние и равные ширины, из представления содержимого в представление прокрутки.), но все же мой взгляд не прокручивался, когда высота внутреннего контроля превысила высоту прокрутки.

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

Внутри моего представления контента у меня есть изображение и 3 надписи под ним. Каждая метка настраивает свою собственную высоту, зависящую от того, сколько текста в них (для этого они установлены в word-wrap и numberoflines = 0).

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

Чтобы исправить это, я должен был установить ограничение Bottom Space на Container между моей нижней меткой и contentview и дал ей значение 40 (выбрано произвольно, чтобы дать ему хороший запас внизу). Теперь это означает, что мой контент-профиль регулирует его высоту, так что между нижней меткой последней метки и самой ей есть пробел, а прокручивается отлично!

Yay!

Ответ 14

Попробуй это...
добавьте все ограничения, например, для UIView (см. экранное изображение моего ViewControler в раскадровке)
введите описание изображения здесь
Теперь трюк начинается. выберите свой последний объект и выберите его нижнее ограничение. (См. Выше screenShot, кнопка Instagram Bottom Constraint (желтая линия)) и измените константу в инспекторе размеров, как показано ниже.

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

Мне требуется Constant = 8, но вы можете изменить в соответствии с вашими требованиями. эта константа - это пространство между этой оранжевой кнопкой внизу и scrollView.

ИЗМЕНИТЬ

Уверяйте свою иерархию просмотров.

0) ViewController.view(необязательный)
1) UIScrollView
2) UIView (переименовать как "contentView" )
3) UIView (это представление - это ваш контент, который будет прокручиваться scrollView)

Ответ 15

Я получил Autolayout для работы с разбивкой по страницам, чьи страницы занимают всю ширину экрана. Страницы автоматически изменяются в соответствии с размером прокрутки. Я не тестировал это для прокрутки с меньшей шириной, но комментирую, если это работает - я полагаю, что это нужно. Целевая для iOS 9, написала код в Swift 2, использовала смесь IB и пользовательский код в awakeFromNib.

Шаги:

  • Определите полноэкранное представление прокрутки.
  • В окне прокрутки добавьте UIView (я назвал my contentView), верхний, конечный, нижний и передний края которого в представлении прокрутки все равны нулю; высота равна просмотру прокрутки; , но ширина - ширина прокрутки, умноженная на количество страниц. Если вы делаете это визуально, вы увидите, что ваше содержимое отображается за пределами вашего прокрутки в Integr Builder.
  • Для каждой "страницы" внутри contentView добавьте правила автоопределения, чтобы поместить их бок о бок друг друга, но самое главное, дать каждому из них ограничение, чтобы их ширина была равна прокрутке, а не просмотр содержимого.

Пример кода ниже. embedChildViewController - это только мой метод удобства добавления дочерних VC - посмотрите setupLayoutRulesForPages. У меня ровно две страницы, поэтому функция слишком проста, но вы можете расширить ее до ваших потребностей.

На мой взгляд, контроллер:

override func loadView() {
    self.view = self.customView
}

override func viewDidLoad() {
super.viewDidLoad()

self.embedChildViewController(self.addExpenseVC, toView: self.customView.contentView, fillSuperview: false)
self.embedChildViewController(self.addCategoryVC, toView: self.customView.contentView, fillSuperview: false)
self.customView.setupLayoutRulesForPages(self.addExpenseVC.view, secondPage: self.addCategoryVC.view)
}

Мое пользовательское представление:

class __AMVCView: UIView {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var contentView: UIView!
    @IBOutlet weak var pageControl: UIPageControl!

    override func awakeFromNib() {
        super.awakeFromNib()

        self.scrollView.pagingEnabled = true
        self.scrollView.bounces = true
        self.scrollView.showsHorizontalScrollIndicator = false
        self.scrollView.showsVerticalScrollIndicator = false

        self.pageControl.numberOfPages = 2

        self.contentView.backgroundColor = UIColor.blueColor()
        self.scrollView.backgroundColor = UIColor.clearColor()
        self.backgroundColor = UIColor.blackColor()
    }

    func setupLayoutRulesForPages(firstPage: UIView, secondPage: UIView) {
        guard self.contentView.subviews.contains(firstPage) && self.contentView.subviews.contains(secondPage)
            else {
                return
        }

        let rules = [
            "H:|-0-[firstPage]-0-[secondPage]-0-|",
            "V:|-0-[firstPage]-0-|",
            "V:|-0-[secondPage]-0-|"
        ]
        let views = [
            "firstPage" : firstPage,
            "secondPage" : secondPage
        ]
        let constraints = NSLayoutConstraint.constraintsWithVisualFormatArray(rules, metrics: nil, views: views)

        UIView.disableAutoresizingMasksInViews(firstPage, secondPage)
        self.addConstraints(constraints)

        // Add the width Autolayout rules to the pages.
        let widthConstraint = NSLayoutConstraint(item: firstPage, attribute: .Width, relatedBy: .Equal, toItem: self.scrollView, attribute: .Width, multiplier: 1, constant: 0)
        self.addConstraint(widthConstraint)
    }

}