UIImageView, setClipsToBounds and how my images are losing their head

VansFannel picture VansFannel · Mar 28, 2012 · Viewed 15.3k times · Source

I'm developing an iOS 4 application.

I'm using this code on an UIImageView on an UITableViewCell:

cell.photo.contentMode = UIViewContentModeScaleAspectFill;
[cell.photo setClipsToBounds:YES];

My images are taller than wide, and when I set UIViewContentModeScaleAspectFill, images are scaled to fit width with UIImageView width. Doing this, the image gets bigger that UIImageView and I see it outside UIImageView.

Then, I need to use setClipsToBounds:YES to don't allow this, but now all my images lose their head.

Is there any way to use UIViewContentModeScaleAspectFill and center top left image corner with top left UIImageView corner? If I need to lose a part of image, I prefer to lose its feet that its head.

UPDATE

I'm using sdWebImage framework and I have used Vadim Yelagin answer and this is my code now:

[cell.photo setImageWithURL:[NSURL URLWithString:entry.photo]
               placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                        success:^(UIImage *image) {
                            CGFloat scaleX = cell.photoBorder.bounds.size.width / image.size.width;
                            CGFloat scaleY = cell.photoBorder.bounds.size.height / image.size.height;
                            CGFloat scale = MAX(scaleX, scaleY);
                            cell.photo.frame = CGRectMake(0, 0, image.size.width * scale, image.size.height * scale);
                            cell.photo.image = image;
                        } 
                        failure:nil];

I have to wait to get all images loaded and reload move around UITableView to see the right image on the right cell (this is because images are cached and it loads faster).

Instead using cell.photo.frame and cell.photo.image I need to pass to block indexPath.row to get the right cell.

I could add a new method to UIImageView+WebCache:

- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder success:(void (^)(UIImage *image, NSInteger row))success failure:(void (^)(NSError *error))failure;
{
    [self setImageWithURL:url placeholderImage:placeholder options:0 success:success failure:failure];
}

But if I do that, I get an error here:

[self setImageWithURL:url placeholderImage:placeholder options:0 success:success failure:failure];

Because now success isn't of type (void (^)(UIImage *image))

Do you know how can I fix this problem?

Answer

Vadim Yelagin picture Vadim Yelagin · Mar 28, 2012

Afaik, the easiest way is to calculate the imageView's frame manually from the size of the image and the frame you want it to fit in.

Create a view with the frame you're currently specifying for your imageView, make the imageView its subview. Set view.clipsToBounds = YES.

Then when you assign an image, do something like

CGFloat scaleX = view.bounds.size.width / image.size.width;
CGFloat scaleY = view.bounds.size.height / image.size.height;
CGFloat scale = MAX(scaleX, scaleY);
imageView.frame = CGRectMake(0, 0, image.size.width * scale, image.size.height * scale);
imageView.image = image;