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
Related
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];
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)
})
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.. :)
I am having issues getting an image to scale properly to my UITableCell. I have a large copy of the image and want to scale by a variable height cell. It is a square image that is x by x.
UIImageView *pw = [[UIImageView alloc] initWithImage:img];
[pw setImage:img];
pw.contentMode = UIViewContentModeScaleAspectFill;
pw.frame = CGRectMake(cell.frame.size.width - img.size.width, cell.frame.origin.y,
?, cell.frame.size.height);
[cell.contentView addSubview:pw];
The issue is I am not sure what value to put for the ? parameter (the image width) since it can scale depending on the height of the cell its in.
If the width of your image depends on the height of the cell you could make it proportional to it. For example,
If the width is the same as the height, make "?" equal to cell.frame.size.height
If the width is 2X the height, make "?" equal to cell.frame.size.height * 2
If the width is half the height, make "?" equal to cell.frame.size.height/2
etc...
Hope this helps!
If it should be a square, put the same in the x direction as the y direction:
CGRectMake(cell.frame.size.width - img.size.width,
cell.frame.origin.y,
cell.frame.size.height,
cell.frame.size.height);
If you use Auto Layout it is easy to do this with height and width constraints on the image view.
One of them is equal to the other one.
Adjust the constant of the other one.
Set needsLayout. Maybe animate.
I have put an UIImageView control on my view with IB.
The size of the control is just something I decided upon, pretty random size really
What I want to do is the control to resize automatically whenever I set the image property to a new image. I want it to actually resize to the size of the image.
Can it be done automatically ? without any code intervention ?
If not - what will the best approach be in this case ?
What happens today is strange. I load images into the ImageView and I see the images getting displayed properly even though the size of the ImageView is not changed. This interferes with my intention of grabbing users touches over the ImageView. The user touches the actual image, but since some parts of the image are outside ( and this is the strange part ) of the ImageView - point mapping goes crazy
Can someone think of any explanation to this ?
thanks
The size of an image has no bearing on how large the UIImageView actually is, rather the size of the UIImageView solely depends on the size given to it in Interface Builder (or that you assigned to it). Else the images would be all whacky when you use the #2x images for Retina displays for example.
If you want to fix this, you must change the frame when setting the image as well. If you're doing this now:
[imageView setImage:[UIImage imageNamed:#"myImage.jpg"]];
change it to:
UIImage img = [UIImage imageNamed:#"myImage.jpg"];
[imageView setImage:img];
imageView.frame = CGRectMake(imageView.frame.origin.x, imageView.frame.origin.y,
img.size.width, img.size.height);
This will however not change the layout of view it is contained within, you can make it change the sizes of the other views automatically under iOS 6 using Layout Constraints. If you are an Apple Developer you can watch the WWDC instruction videos, they explain how that system works quite well.
If you're fine with the view not growing, and the problem is just how the image overflows it's bounds when you change it to one that does not match the dimension of the containing view, you can set the "Clip Subviews" checkbox in Interface Builder for the image view. This will make it so that the view will not draw anything outside it's own bounding box, if you also set the scaling mode to "Aspect Fill" or "Scale To Fill", the image will always fill up the entire bounds of the containing view.
Here is the code snippet I cut and paste often, using the same method as Hampus Nilsson above -
Example
func demo(x0:CGFloat, y0:CGFloat) {
let imgView = UIImageView(image: UIImage(named: "someImg.png"));
imgView.sizeToImage();
imgView.center = CGPoint(x:x0, y:y0);
}
UIImageView Extension
extension UIImageView {
/******************************************************************************/
/** #fcn sizeToImage()
* #brief size view to image
* ##assum (image!=nil)
*/
/******************************************************************************/
func sizeToImage() {
//Grab loc
let xC = self.center.x;
let yC = self.center.y;
//Size to fit
self.frame = CGRect (x: 0, y: 0, width: (self.image?.size.width)!/2, height: (self.image?.size.height)!/2);
//Move to loc
self.center = CGPoint(x:xC, y:yC);
return;
}
A wonderful cut & paste, use if needed!
let containerView = UIView(frame: CGRect(x:0,y:0,width:320,height:500))
let imageView = UIImageView()
if let image = UIImage(named: "Image_Name_Here") {
let ratio = image.size.width / image.size.height
if containerView.frame.width > containerView.frame.height {
let newHeight = containerView.frame.width / ratio
imageView.frame.size = CGSize(width: containerView.frame.width, height: newHeight)
}
else{
let newWidth = containerView.frame.height * ratio
imageView.frame.size = CGSize(width: newWidth, height: containerView.frame.height)
}
}