Как настроить subviews с AutoLayout в UIScrollView программно?

Я создаю приложение с UiScrollview и UIPagectontrol, используя Autolayout Progrmatically, для

Я создал TKScroller как подкласс UIView, я инициализирую его с помощью некоторого режима и массива.

TKScroller.m

-(void)setData{

[self layoutIfNeeded];
CGRect mainFrame=self.frame;


[self layoutIfNeeded];
CGRect mainFrame=self.frame;
UIView *lastview;
NSMutableArray* manualConstraints = [NSMutableArray array];

for (int i=0; i<arrayData.count ; i++)
{
    CGRect frame;
    frame.origin.x = scrollView.frame.size.width * i;
    frame.origin.y = 0;
    frame.size = scrollView.frame.size;

    UIView *subview = [UIView new];

    subview.backgroundColor = [self getRandomColor];
    [scrollView addSubview:subview];

    if (i==0)
    {

        NSLayoutConstraint* b1_top = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeTop multiplier:1 constant:5];
        [manualConstraints addObject:b1_top];

        NSLayoutConstraint* b1_left = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeLeading multiplier:1 constant:5];
        [manualConstraints addObject:b1_left];

        NSLayoutConstraint* b1_right = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeTrailing multiplier:1 constant:-5];
        [manualConstraints addObject:b1_right];
        NSLayoutConstraint* b1_bottom = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeTop multiplier:1 constant:-10];
        [manualConstraints addObject:b1_bottom];

        [subview layoutIfNeeded];
        [scrollView addConstraints:manualConstraints];
        lastview=subview;
    }
    else{

        NSLayoutConstraint* b1_top = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeTop multiplier:1 constant:5];
        [manualConstraints addObject:b1_top];

        NSLayoutConstraint* b1_left = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:lastview attribute:NSLayoutAttributeLeading multiplier:1 constant:5];
        [manualConstraints addObject:b1_left];

        NSLayoutConstraint* b1_right = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeTrailing multiplier:1 constant:-5];
        [manualConstraints addObject:b1_right];
        NSLayoutConstraint* b1_bottom = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeTop multiplier:1 constant:-10];
        [manualConstraints addObject:b1_bottom];

        [subview layoutIfNeeded];
        [scrollView addConstraints:manualConstraints];
        lastview=subview;

    }
}

scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * arrayData.count, mainFrame.size.height/2);

self.pageControl.currentPage = 0;
self.pageControl.numberOfPages = arrayData.count;

 pageControlBeingUsed = NO;
}

-(UIColor *)getRandomColor{
    int r = arc4random() % 255;
    int g = arc4random() % 255;
    int b = arc4random() % 255;
    return [UIColor colorWithRed:(r/255.0) green:(g/255.0) blue:(b/255.0) alpha:1.0];
}

Сейчас я получаю какие-либо подзаголовки,

но если я изменю ориентацию, это даст неверный результат. Так как я могу дать NSLayoutConstraint для подзаголовков scrollview?

ИЗМЕНИТЬ

После добавления NSLayoutConstraint subviews не отображаются. Я просто пропущу какое-то ограничение, пожалуйста, исправьте меня при установлении ограничений динамически.

Мой Исходный код здесь. Пожалуйста, помогите мне. Спасибо. И извините за плохую грамматику.

Ответ 1

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

Alternative

Скорее это ограничение установки вы можете установить только кадр подвью и установить его в Scrollview, и на основе ориентации вы можете изменить кадры подпрограммы scrolview.

Ваш метод setData,

-(void)setData{

    [self layoutIfNeeded];
    CGRect mainFrame=scrollView.frame;
    CGRect frame;
    for (int i=0; i<arrayData.count ; i++)
    {
        CGRect frame;
        frame.origin.x = scrollView.frame.size.width * i;
        frame.origin.y = 0;
        frame.size = scrollView.frame.size;

        frame.origin=CGPointMake(0, 0);
        UIView *subview = [[UIView alloc]initWithFrame:frame];
        subview.backgroundColor = [self getRandomColor];
        [scrollView addSubview:subview];
    }
    scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * arrayData.count, mainFrame.size.height/2);
}

Теперь вы используете NSNotificationCenter, вы можете получать уведомления о том, как настроить ориентацию устройства, поэтому в этом методе выбора вы вызываете свой метод setData,

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(setData)
                                                 name:UIDeviceOrientationDidChangeNotification
                                               object:nil];

Теперь, когда вы устанавливаете метод setData, вам нужно удалить все подзаголовки, потому что, когда устройство меняет ориентацию, оно добавит новые виды в ваш scrollview, поэтому удалите все subview из Scrollview перед установкой его фрейма,

        [scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];

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

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

Ответ 2

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

Вы должны сделать один UIView и только один, который вы добавите в качестве подзаголовка вашего UIScrollView.

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

Здесь подробно объяснено: Техническая нота Apple iOS TN2154

Ответ 3

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

Ниже приведен код для добавления прокрутки в uiviewcontroller

  self.scrollView = UIScrollView()
    self.scrollView.backgroundColor = UIColor.greenColor()
    self.scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
    self.scrollView.scrollEnabled=true
    self.scrollView.pagingEnabled = true
    self.view.addSubview(self.scrollView)

    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[scrollView]|", options: NSLayoutFormatOptions(0), metrics: nil, views: ["scrollView":self.scrollView]))

    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[scrollView]|", options: NSLayoutFormatOptions(0), metrics: nil, views: ["scrollView":self.scrollView]))

После добавления scrollview и добавления подвью/изображений, подобных этому (это пример для изображений, отображаемых в полном размере scrollview, например, в приложении для фотографий)

var prev:UIImgeView?

        for var index = 0; index < self.images.count; ++index {
            var iview = UIImgeView()
            iview.setTranslatesAutoresizingMaskIntoConstraints(false)
            self.scrollView.addSubview(iview)
            var image = self.images.objectAtIndex(index) as UIImage
            iview.image = image
            if (index == 0){
                self.scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[iview(==scrollView)]", options: NSLayoutFormatOptions(0), metrics: nil, views: ["iview":iview,"scrollView":self.scrollView]))
                prev = iview

            }
            else{
                self.scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[prev][iview(==prev)]", options: NSLayoutFormatOptions(0), metrics: nil, views: ["iview":iview,"prev":prev!]))
                prev = iview
            }
            self.scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[iview(==scrollView)]|", options: NSLayoutFormatOptions(0), metrics: nil, views: ["iview":iview,"scrollView":self.scrollView]))

            if (index == self.images.count-1){
                self.scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[prev]|", options: NSLayoutFormatOptions(0), metrics: nil, views: ["prev":prev!]))

            }

        }

Ответ 4

Если вы хотите, чтобы ваш TKScroller был зафиксирован в центре и поддерживал изменения ориентации, вы можете просто поместить следующий код в свой init

self.autoresizingMask = UIViewAutoresizingFlexibleWidth;

и вам может потребоваться проверить все ваши подпрограммы TKScroller. Если вам не нравится автосоздание, вы можете установить (один из трех)

self.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
self.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
self.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;