Search code examples
iosiphoneuiscrollviewautolayoutnslayoutconstraint

How to set subviews with AutoLayout in UIScrollView programmatically?


I am creating app with UiScrollview and UIPagectontrol using Autolayout Programmatically, for

I have Created TKScroller as subclass of UIView, I am init it using Some Mode and Array.

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];
}

Right now i am getting any subviews,

but if i change orientation it will give incorrect result, So how can i give NSLayoutConstraint for subviews of scrollview ?

EDIT

After adding NSLayoutConstraint subviews are not shown. I am just missing some constraint , please correct me in setting constraints dynamically.

My Source Code is here , Please Help Me. Thank you. And Sorry for bad grammar.


Solution

  • Here is a SO answer has explained how to do this with auto layout, he has explain perfectly , In here there is vertically textfields are there But in your case it is you have to set Horizontal views constraints.

    Alternative

    Rather that setting constraints you can set just frame of the subview and set it in Scrollview, And based on orientation you can change frames of the scrolview's subviews.

    Your setData Method like,

    -(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);
    }
    

    Now you using NSNotificationCenter you can get notify when device orientation chaged, so in this selector method of it call your setData method,

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

    Now in you setData method you need remove all subviews because when device changes Orientation it will add new views to your scrollview, so remove all subview from Scrollview before setting its frame,

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

    Make sure you are removing observer from your class like,

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