Loading Remote images in TableView while keeping sizes intact - ios

I want to show a table view where each cell will just contain one image. Images are loaded from respective URLs and there is no restriction on the size of the image.
I want to show the image in each cell with their proper sizes - that is maintain the aspect ratio. I am guessing this would entail having dynamic heights for each cell. But I am not sure and can't find a resource which explains how to achieve this.
What would be the best way to do this?

You need to get the image height and width dynamically first and set the same hieght and width to your table view cells.
I have not added table view but just some code will help you see how you can show two different images with their original height and width and adding the same to a view.
NSURL *imageURL1 = [NSURL URLWithString:#"http://cdn.macrumors.com/article-new/2014/12/applelogo.png"];
NSData *imageData1 = [NSData dataWithContentsOfURL:imageURL1];
UIImage *image1 = [UIImage imageWithData:imageData1];
UIImageView *imageView1 = [[UIImageView alloc] initWithImage: image1];
//CGFloat height = imageView.frame.size.height;
//CGFloat width = imageView.frame.size.width;
[self.view addSubview:imageView1];
//sample urls :- http://pre01.deviantart.net/e711/th/pre/f/2013/179/2/c/ios_7_icons__updated__by_iynque-d69mme1.png
NSURL *imageURL2 = [NSURL URLWithString:#"http://icons.iconarchive.com/icons/position-relative/social-2/128/ios-icon.png"];
NSData *imageData2 = [NSData dataWithContentsOfURL:imageURL2];
UIImage *image2 = [UIImage imageWithData:imageData2];
UIImageView *imageView2 = [[UIImageView alloc] initWithImage: image2];
CGFloat height = imageView2.frame.size.height;
CGFloat width = imageView2.frame.size.width;
imageView2.frame = CGRectMake(0, 300, width, height);
NSLog(#"height :- %f, Width :- %f ",height, width);
[self.view addSubview:imageView2];

Hopefully, you are loading the images asynchronously, as answered here: Loading images for UITableViewCell from URL (need to load them asynchronously)
You'll need a custom cell or prototype cell with a UIImageView set to UIViewContentModeScaleAspectFit. In the cell, set the constraints how you want them: that is, if you want the image to be the full width of the screen, set leading and trailing constraints, and constrain to the top and bottom.
Then, set your table view to use dynamic sizing:
tableView.estimatedRowHeight = 80.0; //or some reasonable first approximation
tableView.rowHeight = UITableViewAutomaticDimension;

Related

UIViewContentModeScaleAspectFit doesn't work

I try to scale my image and i want use Aspect Fit. But it doesn't work
solutionImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bg_solution#2x.png"]];
// optional:
solutionImageView.contentMode = UIViewContentModeScaleAspectFit; // content mode
solutionImageView.center = CGPointMake((currentWidth)/2, currentHeight - (currentHeight/3.5));
[self.view addSubview:solutionImageView];
As arunit21 said in his comment, when you create an UIImageView with the initWithImage method, the size of frame of the view is calculated with image size. So your image view is centered but bigger than you window.
You can do
solutionImageView = [[UIImageView alloc] initWithFrame:yourFrame];
solutionImageView.image = [UIImage imageNamed:#"bg_solution"];
solutionImageView.contentMode = UIViewContentModeScaleAspectFit; // content mode
solutionImageView.center = CGPointMake((currentWidth)/2, currentHeight - (currentHeight/3.5));
[self.view addSubview:solutionImageView];
You can also just set your new frame after your initialization to set the correct size.
The #2x.pngis not needed in [UIImage imageNamed:#"bg_solution"]. With this method, the system will check if the screen is retina and look for the #2ximage if it exists and take the normal one otherwise.

iOS - Cell image blurred

I have placed an image in a UITableViewCell and for some reason, the image is a bit blurred...
This is what I'm using:
NSURL *urlForProfileImage = [NSURL URLWithString: [_currentTweet[#"user"] objectForKey:#"profile_image_url_https"]];
UIImage *thumbnail = [UIImage imageWithData: [NSData dataWithContentsOfURL:urlForProfileImage]];
cell.imageView.image = thumbnail;
Is there another way to provide the desired result but maintain the images quality?
Reason :
The default imageView size is 40x40 and so your image needs to be 80x80 pixels (retina display).
But the image that you are getting from the "pbs.twimg.com/profile_images/192098593/Apple_normal.png" is 48x48.
And so it is blurred.
Solution :
One option is that you add a custom imageView which is 24x24. (width : 24 & height : 24) Then your image will not show blurred.
Or, you can try modifying the height and width of the imageView by subclassing the class UITableViewCell and using its layoutSubviews method. The "trick" is to write layout code in this method, otherwise the code does not have any effect :
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.bounds = CGRectMake(0,0,24,24);
self.imageView.frame = CGRectMake(0,0,24,24);
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
CGRect tmpFrame = self.textLabel.frame;
tmpFrame.origin.x = 30;
self.textLabel.frame = tmpFrame;
tmpFrame = self.detailTextLabel.frame;
tmpFrame.origin.x = 30;
self.detailTextLabel.frame = tmpFrame;
}

UIImageView and autolayout

I have a view that is set up nicely using autolayout. The view contains a series of labels stacked from top to bottom. I am allowing the intrinsic size of these labels to determine the size of the view.
The final step is to add a background from an image. I started by trying the colorWithPatternImage method on UIColor but this isn't quite what I am looking for. I do not want to tile the image, and I can not guarantee it will always be larger than the intrinsic size of the view.
Similarly, adding a uiImageView to the view itself doesn't quite work. The view will expand to accommodate the image when I want to keep the intrinsic size based on the labels.
I guess what I am looking for is the following.
1) The background should have no effect on the size of the view.
2) The image should be scaled to fill the view but in it's original aspect ration (so cropping edges if necessary).
Any ideas appreciated.
In my case, I needed it for a UIImageView inside a dynamically-sized view in a UITableViewCell, but the image refused to shrink below its instristic size and instead worked as a minimum-size constraint for the superview. The only way I could get it ignore the intristic size is by lowering the priority at which it is enforced, right after creating the cell:
[imageView setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
forAxis:UILayoutConstraintAxisHorizontal];
[imageView setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
forAxis:UILayoutConstraintAxisVertical];
After this, all my constraints magically started working. In the OP's case, setting UIViewContentModeScaleAspectFill is also required, as per Mundi's answer.
In Interface Builder, add a UIImageView as the first subview to the view. Make sure its size always matches the view.
Then, in Interface Builder or code, set the contentMode:
backgroundImageView.contentMode = UIViewContentModeScaleAspectFill;
Here's how I would approach this. Hopefully it helps. :)
CGRect contentFrame = CGRectMake(0, 0, self.view.frame.size.width, 0); // This will be the frame used to create the background image view.
UIEdgeInsets contentInsets = UIEdgeInsetsMake(20, 20, 20, 20); // The margins by which the labels will be inset from the edge of their parent view.
CGFloat labelHeight = 21;
CGFloat verticalGap = 8; // The vertical space between labels
CGFloat y = contentInsets.top;
int numberOfLabels = 10;
for (int i = 0; i < numberOfLabels; i++) {
CGRect frame = CGRectMake(contentInsets.left, y, self.view.frame.size.width - (contentInsets.left + contentInsets.right), labelHeight);
UILabel *label = [[[UILabel alloc] initWithFrame: frame] autorelease];
// customize the label here
[self.view addSubview: label];
contentFrame = CGRectUnion(contentFrame, label.frame);
y += labelHeight + verticalGap;
}
contentFrame.size.height += contentInsets.bottom;
UIImageView *backgroundImageView = [[[UIImageView alloc] initWithFrame: contentFrame] autorelease];
[backgroundImageView setClipsToBounds: YES];
[backgroundImageView setContentMode: UIViewContentModeScaleAspectFill];
[backgroundImageView setImage: [UIImage imageNamed: #"background_image.png"]];
[self.view insertSubview: backgroundImageView atIndex: 0];

Stopping UIScrollView at specific place while scrolling with pagingEnabled

I have the following code to create a scroll view with additional area at the beginning and the end of the images (50 points).
UIScrollView* scroll = [[UIScrollView alloc] initWithFrame: CGRectMake(0,0,200,100)];
scroll.contentSize = CGSizeMake(400,100);
UIImageView* img1 = [[UIImageView alloc] initWithFrame: CGRectMake(50,0,100,100);
UIImageView* img2 = [[UIImageView alloc] initWithFrame: CGRectMake(150,0,100,100);
UIImageView* img3 = [[UIImageView alloc] initWithFrame: CGRectMake(250,0,100,100);
//Adding images to ImageViews
scroll.pagingEnabled = YES;
[scroll addSubView:img1];
[scroll addSubView:img2];
[scroll addSubView:img3];
The first time I see the view, I will see the additional area on the left (0-50), then the first image (50-150) and then half of the second image (150-200).
When I swipe left, I want to see half of the first image on the right, the second image at the center, and half of the third image on the right.
When I swipe left again, I want to see the third image at center, with half of the second image on the left, and the additional area on the right.
Can it be possible?
It's possible as long as you define everything correctly. Make sure that the assigned content size is equal to the overall size that you wish to scroll through. Make sure that each page size is equal to the scroll view's frame. You can set the clipsToBounds to NO if the frame clips your subviews.
You can do this by adjusting the contentSize of UIScrollView
- (void)addImagesToScrollView{
//An offset from where imageViewStarts
CGFloat xOffset = 50.0f;
CGRect imageViewFrame = CGRectMake(xOffset, 0.0f, 100.0f, 100.0f);
for (NSString *imageName in #[#"image1.jpg",#"image2.jpg",#"image3.jpg"])
{
UIImageView *imageView = [[UIImageView alloc]initWithFrame:imageViewFrame];
UIImage *image = [UIImage imageNamed:imageName];
imageView.image = image;
[self.scrollView addSubview:imageView];
imageViewFrame.origin.x+=imageViewFrame.size.width;
}
CGSize contentSize = self.scrollView.frame.size;
//Content size is calculate from the imageViewFrame and an offset is added to it
contentSize.width = imageViewFrame.origin.x+xOffset;
[self.scrollView setContentSize:contentSize];
}
Source Code
You can scroll to a particular place in the scrollview using the following code
[YOURSCROLLVIEW setContentOffset:CGPointMake(x, y) animated:YES];

Can you display a small image in a detailTextLabel cell?

So I was wondering if it is possible to display a small image in a detailTextLabel of a cell? (I'm getting the image from a URL) I tried it with:
NSString *thumbs = [NSString stringWithFormat:#"%#", TableText3];
cell.detailTextLabel.text = thumbs;
Which for obvious reason doesn't work. I also tried with:
UIImage *thumbs = [UIImage imageWithData:[NSData dataWithContentsOfURL:
[NSURL URLWithString:TableText3]]];
cell.detailTextLabel.text = thumbs;
Which also (obviously) doesn't work, because I'm passing an image to a string parameter.
Surprisingly I didn't find anything on the WWW. (Search parameters were: "image in detailTextLabel" or picture or just textlabel and image and various variations)
You can't put it directly into the label because labels only display text. But you can use the imageView property of the UITableViewCell.
cell.imageView = [[UIImageView alloc] initWithImage: thumbs];
https://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewCell_Class/Reference/Reference.html
Rather than putting the image in the imageView property, you could create an UIImageView and place it in the accessoryView property:
UIImage * thumbs;
UIImageView * thumbsView;
CGFloat width;
thumbs = [UIImage imageWithData:[NSData dataWithContentsOfURL:
[NSURL URLWithString:TableText3]]];
thumbsView = [[[UIImageView alloc] initWithImage:thumbs] autorelease];
width = (cell.frame.size.height * thumbs.size.width) / thumbs.size.height;
thumbsView.frame = CGRectMake(0, 0, width, cell.frame.size.height);
cell.accessoryView = thumbsView;
This will size the image to fit within the cell and position it to the right of the textLabel and detailTextLabel.
A better approach is not to rely on the built-in UITableViewCell types and create your own cell frame and add all the labels, view, images at your desired position inside the cell. Then you can return the cell for your tableview.

Resources