UITableView and thumbnails - ios

UITableView has UIImageView, all images has the same size. But when I starting scroll or selecting row, some images can change size. I cannot understand why. Or how to make an imageview of a fixed size in a table row?

Use UIGraphicsImageContext with the table view cell image view like :
UIImage *thumbNail = [UIImage imageNamed:[_imageArray objectAtIndex:indexPath.row]];
// Setting thumbnail image
CGSize itemSize = CGSizeMake(60, 40);// Sample image size
UIGraphicsBeginImageContext(itemSize);
CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
[thumbNail drawInRect:imageRect];
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

You can do one thing.. Use custom cell and set imageView's frame there.

Related

Should we scale image before setting it to a imageView in UITableView

I am displaying a list of images with names, with a chevron accessory to see the full size version of selected image.
I see that the scrolling performance is not super smooth. I think the reason is that the image I am assigning to the imageView of each cell is the full size image (which gets scaled down automatically before display).
Will the performance improve if I maintain a smaller image that is of "thumbnail" size? If yes, what is the best way to do this? I see some example in How to resize images in UITableViewCell?. Is the answer (reproduced below) that uses the approach below, good enough?
Also, any other tips to make the scrolling smoother?
CGSize itemSize = CGSizeMake(30, 30);
UIGraphicsBeginImageContext(itemSize);
CGRect imageRect = CGRectMake(30.0, 30.0, itemSize.width, itemSize.height);
[thumbnail drawInRect:imageRect];
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Yes, scaling down image helps a lot. I created the method below to resize following (and call it on a background thread to keep main UI thread humming)
I also, found calling reloadData on only the row that changed helps using
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
Method used to downsize.
- (UIImage *) returnThumbnail:(UIImage*)image
{
CGSize itemSize = CGSizeMake(120, 90);
UIGraphicsBeginImageContext(itemSize);
CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
[image drawInRect:imageRect];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSLog(#"Returning scaled image %#",scaledImage) ;
return scaledImage ;
}

The Image Size Issue Coming From Server In IOS

I am working on application in which the images are coming from server which i have to display in UIImageview which size is of screen size. the problem is some image resolution are very bigger. So, when I use AspectFill it does not appear properly, it is getting shrink and when I use AspectFit it appears in rectangle shape in image view . so is there any way to display image in UIImageView without getting shrink and without getting croped.
Thanks in advance
I think changing contentMode to UIViewContentModeScaleToFill of your imageView should help:
yourImageView.image = yourImage;
yourImageView.contentMode = UIViewContentModeScaleToFill;
CGRect frame = someImageView.frame;
frame.size = yourImage.size;
yourImageView.frame = frame;
Try this
-(UIImage*)resizeImage:(UIImage *)image imageSize:(CGSize)size
{
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0,0,size.width,size.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
//here is the scaled image which has been changed to the size specified
UIGraphicsEndImageContext();
return newImage;
}
And then use new image for your imageView
You can set image using
UIImage * image=[UIImage imageNamed:#"image.png"];
CGSize size=CGSizeMake(50, 63);//set the width and height
UIImage resizedImage= [self resizeImage:image imageSize:size];
Hope it helps.
try :
UIImageView *yourImageView = [[UIImageView alloc] initWithFrame:CGRectMake(x, y, width, height)];
yourImageView.contentMode = UIViewContentModeRedraw;
yourImageView.image = yourImage;
i hope it helps.

How to tile a UIImage vertically while only streching horizontally on iOS?

I have an image that can be stretched in the horizontal direction, but need to be tiled vertically (one on top of the other) to fill my view. How could I do this?
I know that an image can be made resizable by using the -(UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets method. So that works great for the horizontal direction but that method cannot be used for the vertical direction it really needs to be tiled, and not stretched in the vertical direction to work.
Now my idea of how this could work is to run a loop that creates a UIImageView with the horizontally stretched image, and simply adjust the frame.origin.y property, then add it as a subview each loop until I've gone past the height of the view. However this seems like an overly complex way of doing this and really not practical when the view need to be resized (on an iPad rotation for example)
Is there a simpler more efficient way of doing this on iOS 6.x?
I used this to tile an image horizontally in a UIImageView:
UIImage *image = [UIImage imageNamed:#"my_image"];
UIImage *tiledImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0) resizingMode:UIImageResizingModeTile];
UIImageView *imageView = [[UIImageView alloc] initWithImage:tiledImage];
This assumes you set the frame of the UIImageView to a larger size than your image asset. If the height is taller than your image, it will also tile vertically.
Have you considered using UIColor's method colorWithPatternImage: to create a repeating pattern and just pass an image with the correct horizontal width?
Code Example:
// On your desired View Controller
- (void)viewDidLoad
{
[super viewDidLoad];
UIImage *patternImage = [UIImage imageNamed:#"repeating_pattern"];
self.view.backgroundColor = [UIColor colorWithPatternImage:patternImage];
// ... do your other stuff here...
}
UIImage *image = [UIImage imageNamed:#"test.png"];
UIImage *resizableImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(0, image.size.width / 2, 0, image.size.width / 2)];
So I've figured out a solution for this. It is I think a little jacky but it works.
Basically what I've done was to create my stretchable image with the left and right caps specified. And then I initialize a UIImageView with it. I then adjust the frame of the image view to the desired width. This will appropriately resize the image that is contained within it.
Then finally I used a piece of code I found that creates a new image by vertically tiling the adjusted image that is now contained in the image view. Notice how instead of accessing the original UIImage I am using the UIImageView view's image property.
The last thing then is to set the new UIImage as the patterned background colour of the view
Here is the code:
// create a strechable image
UIImage *image = [[UIImage imageNamed:#"progressBackgroundTop#2x.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 60, 0, 60)];
// create the image view that will contain it
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
CGRect frame = imageView.frame;
frame.size.width = self.view.bounds.size.width;
imageView.frame = frame;
// create the tiled image
CGSize imageViewSize = imageView.bounds.size;
UIGraphicsBeginImageContext(imageViewSize);
CGContextRef imageContext = UIGraphicsGetCurrentContext();
CGContextDrawTiledImage(imageContext, (CGRect){ CGPointZero, imageViewSize }, imageView.image.CGImage);
UIImage *finishedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.view.backgroundColor = [UIColor colorWithPatternImage:finishedImage];

How to set MediaItemArtwork Image Fill in UITableViewCell in iOS?

I am trying to enter MPMediaItemArtwork Image into UITableView's cell's ImageView with following code.
MPMediaItemArtwork *artwork = [[[self.arrayOfAlbums objectAtIndex:indexPath.row] representativeItem]valueForProperty:MPMediaItemPropertyArtwork];
UIImage *artworkImage = [artwork imageWithSize: cell.imageView.bounds.size];
if (artworkImage)
{
cell.imageView.image = artworkImage;
}
else
{
cell.imageView.image = [UIImage imageNamed: #"noArtwork.png"];
}
It's okay when i insert Artwork image in UITableView's cell ImageView.
But when my artwork image is too small or big , it's happened like following pic.
Not in completely fill in cell's ImageView.
You see that? I want to set Fill with Stretch like iOS Music App
Here is Build-in App Artwork Image that set Completely fill with Stretch
I want to do like that.
So i used cell.imageView.contentMode = UIViewContentModeScaleAspectFill; however it's not effect.
So how can i do that?
Thanks you for your work.
Try this for calculating a new and fitting image;
Adjust newRect to the rect of your cell.
// scale and center the image
CGSize sourceImageSize = [artworkImage size];
// The rectangle of the new image
CGRect newRect;
newRect = CGRectMake(0, 0, 40, 33);
// Figure out a scaling ratio to make sure we maintain the same aspect ratio
float ratio = MAX(newRect.size.width / sourceImageSize.width, newRect.size.height / sourceImageSize.height);
UIGraphicsBeginImageContextWithOptions(newRect.size, NO, 1.0);
// Center the image in the thumbnail rectangle
CGRect projectRect;
projectRect.size.width = ratio * sourceImageSize.width;
projectRect.size.height = ratio * sourceImageSize.height;
projectRect.origin.x = (newRect.size.width - projectRect.size.width) / 2.0;
projectRect.origin.y = (newRect.size.height - projectRect.size.height) / 2.0;
[sourceImage drawInRect:projectRect];
UIImage *sizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
cell.imageView.image = sizedImage;
The line
UIImage *artworkImage = [artwork imageWithSize: cell.imageView.bounds.size];
creates an image with the size of the cell. So, it's scaled in this line and the image won't be bigger than the cell and therefore it will not scale afterwards.
I would leave the image at it's original size or at a size 2x the cell size and leave the scaling up to contentMode.
CGSize newSize = CGSizeMake(artwork.bounds.size.width, artwork.bounds.size.height)
UIImage *artworkImage = [artwork imageWithSize: newSize];

How to make UITableView not change imageView's frame, or resize the image to fill the frame size?

In tableView:cellForRowAtIndexPath, I am setting imageView.image to a 1x1, or 60x60 placeholder image, while the cell's height is 300. I also set imageView.frame to (0,0, 300, 300).
Then I call a method downloadImageFromURL:andSetIntoCell, which immediately add a UIActivityIndicatorView and set the frame to (0,0, 300, 300) (the download is done asynchronously in a thread, and the method won't wait for the download but just return immediately).
However, after tableView:cellForRowAtIndexPath return the cell, imageView.frame is adjusted to vertically center the image of original 60x60 size. If that placeholder image is 800x800, it actually works fine: the frame is still (0,0, 300, 300) and the image is scaled down, but when the image is 60x60, the frame is actually adjusted to something like (0,120, 60, 60), that is ok because the placeholder is transparent, but the UIActivityIndicatorView was added as a subview of imageView, and therefore get pushed down vertically, having a height of 300 and cover up part of the next row.
Is there a way to tell UITableView not to change imageView.frame, or easily resize the image to 300x300 programmatically (preferably not to use BitmapContext), or tell imageView to scale to fill the frame?
I added:
cell.imageView.contentMode = UIViewContentModeScaleToFill;
after setting imageView.frame, which normally works if I am drawing on a UIView, but UITableView will still show the original 60x60 size, and adjust imageView.frame to vertically center it.
(I think in this case I can just make UIActivityIndicatorView the size of the image: 60x60, but supposedly it is to do it with a 1x1 transparent placeholder image)
Update: by the way, I even added:
self.table.autoresizesSubviews = NO;
self.table.autoresizingMask = UIViewAutoresizingNone;
cell.autoresizesSubviews = NO;
cell.autoresizingMask = UIViewAutoresizingNone;
cell.imageView.autoresizesSubviews = NO;
cell.imageView.autoresizingMask = UIViewAutoresizingNone;
before the cell is returned, and it is the same: the imageView is repositioned and resized.
The frames of cell's imageview is not changing later on. So using layoutSubviews, I resolve this matter as follows:-
Set the image using AFNetworking's method named setImageWithURLRequest: I use the 64*64 size for my example. You can alter the frames which are applicable to your table view.
NSURL *urlMapThumbnail = [NSURL URLWithString:#"https://maps.googleapis.com/maps/api/staticmap?zoom=8&size=65x65&maptype=roadmap&markers=color:red%7Clabel:S%7C28.5002761,77.08126909999999"];
__weak UITableViewCell *cellTemp = cell;
[cell.imageView setImageWithURLRequest:[NSURLRequest requestWithURL:urlMapThumbnail]
placeholderImage:[UIImage imageNamed:#"sotrelocation"]
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
CGSize finalSize = CGSizeMake(64, 64);
image = [UIImage imageWithImage:image scaledToSize:finalSize];
cellTemp.imageView.image = image;
[cellTemp layoutSubviews];
} failure:nil];
//Method to re-scale the image size
+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
//UIGraphicsBeginImageContext(newSize);
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

Resources