laying out images in UIScrollView automatically

2019-02-19 08:15发布

i have a list of images retrieved from xml i want to populate them to a uiscrollview in an order such that it will look like this.

1 2 3

4 5 6

7 8 9

10

if there is only 10 images it will just stop here.

right now my current code is this

for (int i = 3; i<[appDelegate.ZensaiALLitems count]-1; i++) {
        UIButton *zenbutton2 =[UIButton buttonWithType:UIButtonTypeCustom];
        Items *ZensaiPLUitems = [appDelegate.ZensaiALLitems objectAtIndex:i];
        NSURL *ZensaiimageSmallURL = [NSURL URLWithString:ZensaiPLUitems.ZensaiimageSmallURL];
        NSLog(@"FVGFVEFV :%@", ZensaiPLUitems.ZensaiimageSmallURL);
        NSData *simageData = [NSData dataWithContentsOfURL:ZensaiimageSmallURL];
        UIImage *itemSmallimage = [UIImage imageWithData:simageData];
        [zenbutton2 setImage:itemSmallimage forState:UIControlStateNormal];
        zenbutton2.frame=CGRectMake( (i*110+i*110)-660 , 300, 200, 250);
        [zenbutton2 addTarget:self action:@selector(ShowNextZensaiPage) forControlEvents:UIControlEventTouchUpInside];
        [scrollView addSubview:zenbutton2];
}

notice the CGRectMake , i have to manually assign fixed values to position them. Is there any way to populate them out without manually assigning. for e.g the images will automatically go down a position once the first row has 3 images and subsequently for the rest.

2条回答
我欲成王,谁敢阻挡
2楼-- · 2019-02-19 09:00

I think you probably want to wrap your loop in another loop, to get what I'm going to call a 2D loop:

for (int row = 0; row < num_rows; row++) {
   for (int col = 0; col < num_cols; col++) {
        // code before
        zenButton2.frame = CGRectMake(origin x dependent on col,
                                      origin y dependent on row,
                                      width,
                                      height);
        // code after
   }
}

Where the x and y of the CGRectMake() are multiples of the width and height of your image times the row and column respectively. Hope that makes sense.

查看更多
兄弟一词,经得起流年.
3楼-- · 2019-02-19 09:04

If I understand what you are saying, you should be able to write a simple block of code that assigns a position based on the image number.

Something like this (where i is the image number, starting from 0):

- (CGPoint)getImageOrigin:(NSInteger)imageNumber {

    CGFloat leftInset = 30;
    CGFloat xOffsetBetweenOrigins = 80;
    CGFloat topInset = 20;
    CGFloat yOffsetBetweenOrigins = 80;

    int numPerRow = 3;

    CGFloat x = leftInset + (xOffsetBetweenOrigins * (imageNumber % numPerRow));
    CGFloat y = topInset + (yOffsetBetweenOrigins * floorf(imageNumber / numPerRow));

    CGPoint imageOrigin = CGPointMake(x, y);

    return imageOrigin;

}

The origin being calculated here is the upper left corner of each image.

To calculate the x value, I start with the minimum distance from the left side of the screen (leftInset). Then, I add the distance from the left side of one image to the next image, multiplied by the column (imageNumber % numPerRow).

Y is calculated in a similar fashion, but to calculate the row, I use the imageNumber / numPerRow rounded down.

Edit:

You asked me to explain further, so I'll see what I can do.

OK, so I want to be able to input the image number (starting at 0) into my function, and I want the origin (upper left corner point) back.

leftInset is the distance between the left edge of the view, and the left edge of the first image.

xOffsetBetweenOrigins is the distance from the left edge of one image to the left edge of the next image on the same row. So, if I set it to 80 and my image is 50px wide, there will be a 30px gap between two images in the same row.

topInset is like left inset. It is the distance from the top edge of the view to the top edge of the images in the top row.

yOffsetBetweenOrigins is the distance from the top edge of an image to the top edge of the image below it. If I set this to 80, and my image is 50px tall, then there will be a 30px vertical gap between rows.

numPerRow is straightforward. It is just the number of images per row.

To calculate the x value of the upper left corner of the image, I always start with the leftInset, because it is constant. If I am on the first image of a row, that will be the entire x value. If I am on the second image of the row, I need to add xOffsetBetweenOrigins once, and if I am on the third, I need to add it twice.

To do this, I use the modulus (%) operator. It gives me the remainder of a division operation, so when I say imageNumber % numPerRow, I am asking for the remainder of imageNumber/numPerRow. If I am on the first image (imageNumber = 0), then 3 goes into 0 no times, and the remainder is 0. If I am on the second image (imageNumber = 1), then I have 1/3. 3 goes into 1 0 times, but the remainder is 1, so I get xOffsetBetweenOrigins*1.

For the y value, I do something similar, but instead of taking the modulus, I simply divide imageNumber/numPerRow and round down. Doing this, I will get 0 for 0, 1, and 2. I will get 1 for 3, 4, and 5.

Edit:

It occurred to me that you might actually have been asking how to use this method. In your code, you would say something like

CGRect newFrame = zenbutton2.frame;
newFrame.origin = [self getImageOrigin:i];
zenbutton2.frame = newFrame;

Another Edit:

Maybe you could try this?

CGPoint origin = [self getImageOrigin:i];
zenbutton2.frame = CGRectMake(origin.x, origin.y, width, height);

If that doesn't work, throw in

NSLog("Origin Values: %f,%f", origin.x, origin.y);

to make sure that you are actually getting something back from getImageOrigin.

查看更多
登录 后发表回答