iOS: UIScrollView leaving space on bottom, How can I have space on top

1.6k Views Asked by At

I have scrollView in which subview are getting added from bottom, like adding bricks in wall (in my case only one brick), then next brick on top of that, like that so on. As with default UIScrollView ContentSize, Scrolling will happen on top. How can I make scrolling to bottom. If I scroll down I should be able to see other bricks which are added one above the other.

As you can see in below screen shots, start button should go down instead of of up.

Any kind of help be very appreciated.

Thanks

Sample Code:

CGFloat initialYPoint = 30;
for (OUSTLevel* currentLevel in self.course.sortedLevelsList) {

    NSArray* nibList = [[UINib nibWithNibName:@"OUSTLearningMapPlayLevelCell" bundle:nil] instantiateWithOwner:self options:nil];
    OUSTLearningMapPlayLevelCell* playLevelCell = nil;

    for (UIView* childView in nibList) {
        if ([childView isKindOfClass:[OUSTLearningMapPlayLevelCell class]]) {
            playLevelCell = (OUSTLearningMapPlayLevelCell*)childView;
            break;
        }
    }

    CGFloat cellHeight = CGRectGetHeight(playLevelCell.frame);
    CGFloat yPoint = CGRectGetHeight(self.scrollview.frame) - (cellHeight + initialYPoint);
    CGRect cellFrame = CGRectMake(0, yPoint, viewWidth, cellHeight);

    [playLevelCell setFrame:cellFrame];      
    [self.scrollview addSubview:playLevelCell];

    initialYPoint += cellHeight;

    if (!landingNodeLevelData.locked) {
        [playLevelCell.unlockedView setHidden:NO];
        [playLevelCell.lockedView setHidden:YES];

        // Frame calculation for placing pin
        CGFloat centerPoint = playLevelCell.unlockedView.frame.size.width / 4;
        pinXPoint = centerPoint + 5;
        pinYPoint = yPoint - 30;
    }
}

CGRect pinFrame = CGRectMake(pinXPoint, pinYPoint, 80, 80);

[self.pinImageView setFrame:pinFrame];
[self.scrollview addSubview:self.pinImageView];
[self.view bringSubviewToFront:self.pinImageView];
self.scrollview.contentSize = CGSizeMake(self.view.frame.size.width, initialYPoint);
self.scrollview.contentInset = UIEdgeInsetsMake(30.0, 0.0, 30.0, 0.0);
CGPoint bottomOffset = CGPointMake(0, self.scrollview.contentSize.height - self.scrollview.bounds.size.height+ 30);

Edit: I am not using constraint layout, I am calculating & setting frame.

First screen

Second screen

Third Screen

enter image description here

1

There are 1 best solutions below

0
DonMag On

It looks like you could make things a bit easier on yourself.

If you Reverse the order of your "brick" stacking, you can be filling the view from the Top-Down instead of Bottom-Up ... which is much more logical and easier to think about.

This is a modification to your pastebin code. It should work fine... I didn't have your data / classes / xib views / etc, but I'm pretty sure I simulated it so this will run without error:

// start with 30-pt "padding" at the top
CGFloat initialYPoint = 30;

// reverse the array of OUSTLevel objects so we're going from top-down instead of bottom-up
NSArray *reversed = [[self.course.sortedLevelsList reverseObjectEnumerator] allObjects];

for (OUSTLevel* currentLevel in reversed) {

    NSArray* nibList = [[UINib nibWithNibName:@"OUSTLearningMapPlayLevelCell" bundle:nil] instantiateWithOwner:self options:nil];
    OUSTLearningMapPlayLevelCell* playLevelCell = nil;

    for (UIView* childView in nibList) {
        if ([childView isKindOfClass:[OUSTLearningMapPlayLevelCell class]]) {
            playLevelCell = (OUSTLearningMapPlayLevelCell*)childView;
            break;
        }
    }

    CGFloat cellHeight = CGRectGetHeight(playLevelCell.frame);

    // we're going top-down now, so Y coordinate will be a simple increment
    CGFloat yPoint = initialYPoint;

    CGRect cellFrame = CGRectMake(0, yPoint, viewWidth, cellHeight);

    [playLevelCell setFrame:cellFrame];

    [self.scrollview addSubview:playLevelCell];

    initialYPoint += cellHeight;

    if (!landingNodeLevelData.locked) {
        [playLevelCell.unlockedView setHidden:NO];
        [playLevelCell.lockedView setHidden:YES];

        // Frame calculation for placing pin
        CGFloat centerPoint = playLevelCell.unlockedView.frame.size.width / 4;
        pinXPoint = centerPoint + 5;
        pinYPoint = yPoint - 30;
    }
}

CGRect pinFrame = CGRectMake(pinXPoint, pinYPoint, 80, 80);

[self.pinImageView setFrame:pinFrame];
[self.scrollview addSubview:self.pinImageView];
[self.view bringSubviewToFront:self.pinImageView];

// add 30-pt "padding" at the bottom
initialYPoint += 30;

// set contentSize
self.scrollview.contentSize = CGSizeMake(cellWidth, initialYPoint);

// we want to initially see the "Start Rocket" visible at the bottom of the scroll view
CGFloat yOffset = scrollview.contentSize.height - scrollview.bounds.size.height;
scrollview.contentOffset = CGPointMake(0, yOffset);

Hope it helps - if anything's not clear, ask away :)