UIImage in self sizing UITableViewCell stretching - ios

So I have a tableview setup so it displays some information text with an image, the text can vary so I've set up the constraints that the cell updates its size by itself, however the images are stretching as shown below and i've checked that the content mode is set to Aspect Fit.
As it can be observed from the image there are 3 Views in the cell:
-The Title
-The Image, which is being stretched
-The description
My constraints are set up as followed:
Title.top = topMargin
Title.trailing = trailingMargin
Title.leading = leadingMargin
Title.height = 32
Image.leading = leadingMargin
Image.top = Title.bottom + 16
bottom.margin = Image.bottom
Image.width = SuperView(content of cell).width * 0.4
text.leading = image.trailing + 16
trailingMargin = text.trailing
bottomMargin = text.bottom
text.top = topMargin + 16
How can I fix this issue so the images don't stretch? If any additional information is needed please ask and i'll add it.
Thanks
-Jorge

Add a height constraint to the image matching its width so that it maintains its square aspect ratio. Or any height for that matter. Just fix the height so that it does not stretch.
image.height = SuperView(content of cell).width * 0.4

For an app I just created, the tableViewCells and images exhibited something similar, stretching after the cell was scrolled off screen and back into view.
Assuming the image is retrieved from a server (or a file with image data), create a UIImage with a scale factor before setting it as the image of the UIImageView in the tableViewCell. I experimented with a few scale factors (instead of calculating, so your results may vary) before setting it as 5... it is better to calculate for production code but in prototyping, this heuristic worked:
UIImage* scaledImage = [[UIImage alloc] initWithData:data scale:5.0f];
// ... On MainThread
[cell.imageView setImage:scaledImage];

Related

AutoLayout: Issue with scaling UIImageView in UIStackView/UITableViewCell

I have a UITableViewCell that contains a UIStackView with views stacked vertically. I have set UITableViewAutomaticDimension as the UITableView's row height and estimated height. One of the subviews of the UIStackView contains two UIImageViews like this:
The little one is avatarImageView and the bigger is messageImageView. Here are the constraints:
avatarImageView:
messageImageView:
Then, I'm trying in cellForRowAt's delegate method to update the height of the messageImageView to match the image scale (and I let a width of 200px for the image view).
let ratio = image.size.width / image.size.height
cell.messageImageViewHeightConstraint?.constant = 200 * ratio
I'm trying to use this image for example:
But it doesn't work at all, the image takes too much space instead and for some reason the avatar image view ends up being hidden (the cell is surrounded in red, above it is a cell with only text that works fine) :
So what am I missing here?
Thanks for your help!
Your ratio is inverted compared to how you are using it:
The easiest fix is to divide by the ratio instead of multiplying by it:
let ratio = image.size.width / image.size.height
cell.messageImageViewHeightConstraint?.constant = 200 / ratio
or if you prefer, change the ratio calculation:
let ratio = image.size.height / image.size.width
cell.messageImageViewHeightConstraint?.constant = 200 * ratio

bounds of imageView are always 240

I have a probably simple mistake that drives me crazy.
I'm working with UIImageView within a UIScrollView. To fit the image in the view I want to get the width of the imageView to adjust the zoom scale.
But the code
imageView.bounds.width
always returns 240.0 no matter what size the actual image has.
In the Interface Builder the imageView is horizontally and verically centered in the view, clip subviews is true and Mode is aspect fit.
Any ideas?
The size of the UIImageView is not related to the size of the image it contains. The UIImageView is probably sized to 240.0 in the storyboard or wherever else you generate it. The image will scale down or up to fit the view based on the mode. To get the size of the actual image, try the following code:
let image = UIImage("my_image_file")
let imageHeight = image.size.height
let imageWidth = image.size.width
With the size of the image now know, you can set the size of the view appropriately.
I had the same problem. Now I check the bounds in the main_queue and everything works fine.
dispatch_async(dispatch_get_main_queue(), {
print(self.image.bounds.width)
})

Unexpected NSLayoutConstraint behaviour in IOS7

I am getting this issue, only in iOS versions prior to 8
The selected view in the very first screen shot is a UIImageView. you can also see the constraints i have connected. I need to make the image view circular, so i am using layer.cornerRadius property. normally for circular UIImageView we use cornerRadius = height/2.0
but when i am setting this property in "viewDidLayoutSubviews" method. some how its giving me a square imageview.
as you can see i have set aspect ratio of image 1:1
so it can be turned into circular UIImageView.
I know I must be missing out some facts about NSLayoutConstraints. please help me out
My Code :-
-(void)viewDidLayoutSubviews
{
float height = profile_InfoSubView_ProfilePic.bounds.size.height;
float width = profile_InfoSubView_ProfilePic.bounds.size.width;
NSLog(#"(w,h)= %0.0f , %0.0f",width,height);
float cr = height/2.0;
profile_InfoSubView_ProfilePic.layer.cornerRadius = cr;
profile_InfoSubView_ProfilePic.layer.masksToBounds = YES;
profile_InfoSubView_ProfilePic.layer.borderWidth = 2.0f;
profile_InfoSubView_ProfilePic.layer.borderColor = [UIColor greenColor].CGColor;
}
Console Output
2015-09-08 10:42:35.156 MyApp[821:60b] (w,h)= 240 , 128
as you can see even after setting image aspect ration to 1:1, its not square
Output On Device (iPhone 4 - iOS 7.1 )

UIImageView with fixed width: how to set its height to keep its aspect?

I have a view where I need to place an UIImageView, and I was told to place it inside a rectangle that takes the screen width and its height is smaller than width (fixed size). However, the images I've been given are more or less square jpeg images, so the idea is to fill the width of the rectangle that should contain the image and set the height of the image in a way that its aspect ratio is kept. Then, I should be able to let the user scroll the image vertically to see the complete image.
How could I do this?
Thanks in advance
EDIT: I need to do this for several images that have different sizes, but that should fit the same rectangular area size within the view
You can set imageview content mode.
imageView.contentMode = UIViewContentModeScaleAspectFit;
This will make sure that the image is displayed by keeping original aspect ratio.
Edit:
I think this is what you wanted:
UIImage *originalImage = [UIImage imageNamed:[picArr objectAtIndex:a]];
double width = originalImage.size.width;
double height = originalImage.size.height;
double apect = width/height;
double nHeight = 320.f/ apect;
self.img.frame = CGRectMake(0, 0, 320, nHeight);
self.img.center = self.view.center;
self.img.image = originalImage;
Hope this helps.. :)

Make an UIImageView and its UIImage scale proportionally without extra padding

I have an UIView that contains a UIImageView. The UIImageViews works like the branding logo of the app. When I rotate the device, the containing UIView resizes itself to correspond to the landscape or portrait proportions of the screen.
What I'm trying to achieve is to have the UIImageView scaled accordingly, keeping proportions also on the left margin.
This is the actual code for the top white "banner":
UIView *topBanner = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, height_topBanner)];
[topBanner setAutoresizingMask:(UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin)];
[topBanner setBackgroundColor:[UIColor whiteColor]];
topBanner.autoresizesSubviews = YES;
// the logo
UIImage *topBanner_logo = [UIImage imageNamed:#"logo.png"];
float logoAspectRatio = topBanner_logo.size.width/topBanner_logo.size.height;
topBanner_logoView = [[UIImageView alloc] initWithFrame:CGRectMake(topBanner.frame.size.width/100*3, topBanner.frame.size.height/100*7, (topBanner.frame.size.height/100*86)*logoAspectRatio, topBanner.frame.size.height/100*86)];
[topBanner_logoView setImage:topBanner_logo];
topBanner_logoView.backgroundColor = [UIColor blueColor];
topBanner_logoView.contentMode = UIViewContentModeScaleAspectFit;
[topBanner_logoView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleRightMargin)];
[topBanner addSubview:topBanner_logoView];
[self.view addSubview:topBanner];
This is my starting point: portrait iPad on startup:
This is what happens when I rotate it in landscape:
As you can see, the proportions of the UIImage are ok, but I'm getting extra borders (I set the background color of the UIImageView to highlight it) because the UIImageView stretches itself to follow the change of the size of its container, and the UIImage is fit into the UIImageView and put on its center.
The same - reversed - happens when I start the app directly in landscape mode:
Then I rotate it:
... and I get the logo with extra borders on top and bottom.
I do see that I can write a function to recalculate every size on each rotation change, but I'm asking to myself if is there a way to set the UIImageView and the UIImage to make it works without hacking the autorotate/resize procedures of iOS. It sounds so simple!
You can solve this by not using UIViewContentModeScaleAspectFit, and instead calculating the aspect ratio of the image and using that to explicitly the width or height based on the other (width or height).
e.g. I rotate to landscape, and so I want the height to be 80% of the view.
CGFloat w = logo.image.size.width;
CGFloat h = logo.image.size.height;
CGFloat a = w / h;
CGFloat h_use = self.view.height *0.8;
CGFloat w_use = h_use*a;
Furthermore, set the content mode to UIViewContentModeScaleAspectFill instead now that you've explicitly set the aspect ratio.
You have set the auto resizing mask to flexible height and width:
[topBanner_logoView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleRightMargin)];
If you do not do that, the default is that the view will not chance size, and therefore, the image will not either.
I think it is because of topBanner_logoView.contentMode = UIViewContentModeScaleAspectFit;
Try topBanner_logoView.contentMode = UIViewContentModeCenter or topBanner_logoView.contentMode = UIViewContentModeLeft to prevent the UIImageView's image from resizing (and getting padding).
If the UIImageView is resizing, remove the autoresizing mask.

Resources