UIImageView frame same as scaled UIImage inside it (with Aspect Fit) - ios

I'm using UIImageView with Content Mode set to Aspect Fit. UIImageView resizes correctly my image but it doesn't change own frame after resizing even there is no constraints set.
What I need:
I need UIImageView to resize own frame according image inside. I've configured image view at Storyboard.
I need to layout again other objects at view because UIImageView's size is changed.
What I've tried:
I've created:
UIViewController (white background) → UIImageView (gray background) → sample image inside it.
Constraints: leading & trailing constraints set to zero, Y constraint is set to align UIImageView vertically.
As you see after image scaled correctly UIImageView's frame is still has incorrect size (gray background).
I've tried to set UIImageView size manually:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let newSize = AVMakeRect(aspectRatio: backgroundImageView.image!.size, insideRect: backgroundImageView.frame)
backgroundImageView.frame = newSize
}
In that example code I've calculated image size and set frame size to image's size. I don't know if it is better way so I don't need to use AVFoundation's methods.
Problem: other object is place incorrectly because UIImageView's size changed and constraints are invalid now.
That methods doesn't work for me:
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
Even I will call my UIImageView size calculation at viewDidLayoutSubviews() other constraints is still using old UIImageView's size.
Questions
How to change UIImageView's size correctly? Maybe I can do it without code? Maybe I need to play with Hugging/Compression? I've tried something but got no luck.
How to force view to recalculate other constraints so they will use new UIImageView size? For example I can put red square at the top of UIImageView, but after UIImageView has been resized by my method, red square still will be at the old UIImageView's position.

Related

Resizing UIImageView frame after scaleAspectFit

I created a UIImageView in IB with a Content Mode of Aspect Fit. I'm then loading a large image to that view from a URL.
#IBOutlet weak var pictureView: UIImageView!
NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data, _, error) -> Void in
guard let data = data where error == nil,
let image = UIImage(data: data)
else {
print(error?.localizedDescription)
return
}
pictureView.image = image
pictureView.clipsToBounds = true
setNeedsLayout()
layoutIfNeeded()
}).resume()
The image loads in the the UIImageView, and Aspect Fit resizes the image correctly to display it all in the frame, however the frame of the UIImageView is set to the size of the original large image. I have this huge frame wrapping this smaller resized image. I need the UIImageView frame to tightly wrap the Aspect Fit UIImage, throwing off all my other formatting.
Do I need to somehow calculate a new frame size manually for the UIImageView, or am I missing a setting somewhere?
EDIT:
I've also tried the following to resize the UIImageView frame around the image:
pictureView.frame = AVMakeRectWithAspectRatioInsideRect(picture.size, pictureView.frame)
and...
pictureView.frame = CGRectMake(self.pictureView.frame.origin.x, self.pictureView.frame.origin.y, pictureImage.size.width, pictureImage.size.height)
And I've also tried playing with the compression resistance settings.
Well there a few things that are involved.
The dependencies :
1) The image size. If the image height/width ratio is not greater than or equal to ImageView height/width ratio, then there will be black space shown, as there will be less ratio to match to the ImageView.
2) I am unsure of the constrains of your imageView, since I can see it is an #IBOutlet.
I am confused on your sentence "however the frame of the UIImageView is set to the size of the original large image. I have this huge frame wrapping this smaller resized image."
I believe what you are wanting to do is set the image into the imageView, but it seems that you are setting the UIImageView into the image size then the image into UIImageView, which makes it really confusing to debug. Could you explain more detailed exactly what you are wanting to happen?
EDIT
There is an ImageView with a frame -- this frame will NEVER be different.
The contentMode will change how the image is displayed on the imageView
The UIViewContentModeScaleAspectFit and UIViewContentModeScaleAspectFill modes scale the image to fit or fill the space while maintaining the image’s original aspect ratio.
The UIViewContentModeScaleToFill value scales the image without regard to the original aspect ratio, which can cause the image to appear distorted.
UIViewContentModeScaleToFill
The option to scale the content to fit the size of itself by changing the aspect ratio of the content if necessary.
*(Wouldn't recommend for most cases)
UIViewContentModeScaleAspectFit
The option to scale the content to fit the size of the view by maintaining the aspect ratio. Any remaining area of the view’s bounds is transparent.
*(This one guarantees that the WHOLE IMAGE fits on the screen. So if the image is smaller ratio than the screen, then there will be black on some edges, either top/bottom or left/right)
UIViewContentModeScaleAspectFill
The option to scale the content to fill the size of the view. Some portion of the content may be clipped to fill the view’s bounds.
*(This one guarantees that the WHOLE IMAGEVIEW is taken)

How to resize a fixed width and height UIImageView with auto layout

I have a view named myView which is always half the screen and sit at the top of screen.
Inside this view I added an UIImageView with 120x120 size which sits in center of the myView (horizontally and vertically). Inside the IB, to satisfy the constraints(X & Y) I always need to set a fixed width and height for my image, after I set center horizontally and center vertically.
But with a fixed height and width, the image doesn't resize when changing the screen size. I want my image to resize when running on iPhone5 or iPhone 4s, because myView will resize.
I need something like the image should depend on the myView size.
How to actually achieve this ?
set imageView.clipToBounds = yes, and also set imageView.contentMode = UIViewContentModeScaleAspectFit;
Update
You are talking about imageView not the image, in that case it will not resize due to constant width and height, do one thing, create IBoutLet of constraint and change there values when required, or you can also set Aspect ratio with superView
If you set the image with fixed width and height it will not change respectively.
You can either set it to be relative to myView or you can instead set leading and trailing size from all for edges and delete the center constrains.
Your constraints should look like this:
For Swift 4: Updating answer of #Adnan Aftab
imageView.clipsToBounds = true
imageView.contentMode = .scaleAspectFit

How to fill the background image in a UIView without streching it

I'm trying to set the background image of a UIView with animated .gif's that I'm pulling form Giphy.
The problem I'm having is that the UIView is stretching the image. I want to fill the background so the height is 100% and have it centered. So left and right of the .gif would be cut off - but the image would be centered on the screen and not stretched.
Here's a screenshot of what it looks like now.
You can see it's fills height correct but it's shrinking the width of the image to match the UIView dimensions making it look stretched.
Here is the code I have now:
override func viewDidAppear(animated: Bool) {
self.giphyBackground(Title: "dancing") { [weak self] (gifUrl) -> Void in
let gifView = FLAnimatedImageView(frame: self!.giphy.frame)
gifView.animatedImage = FLAnimatedImage(animatedGIFData: NSData(contentsOfURL: NSURL(string: gifUrl)!)!)
self?.view.insertSubview(gifView, aboveSubview: self!.giphy)
}
}
Any ideas
I think you should set the content mode of gifView to Aspect Fit, doing so will not stretch the image and will fully fill at-least one of the length either horizontally/ vertically.
Try setting
gifView.contentMode = UIViewContentMode.ScaleAspectFit
Also you can use scale AspectFill on gifView as
gifView.contentMode = UIViewContentMode.ScaleAspectFill
ScaleAspectFill will fill the entire gifView's frame but will also maintain the aspect ratio, doing so your image won't look stretched but it could happen that content either horizontally or vertically will go outside the frame(which you can clip).
You are definitely looking for the view's contentMode ScaleAspectFit. Simply add a line gifView.contentMode=UIViewContentMode.ScaleAspectFit

Change the size of the background image codewise from a label in swift

In the app that I am making I have some background images for some labels.
The image is 500x550 pixels but my label is 250x275 pixels.
How can I make the code change the width and height of the background so it fits the size of the label?
Code I have now:
lblMainNumber.backgroundColor = UIColor(patternImage: UIImage(named: "image.png")!)
It is easier to have a container UIView with size of 250 x 275 that will contain 2 subviews with same size:
1) a UIImageView with your image (set its contentMode to UIViewContentModeScaleAspectFit)
2) UILabel with your text. It will be on top of the UIImageView to stay visible.
You would possibly want to set both subviews (via autolayout) to match the size of container view.
Pattern image approach is pain in the ass and not wort the effort.

UIImageView overflowing its containing UIView after calling sizeToFit

My UIView (width: 352px) has a UIImageView subview (default width in Storyboard: 312px).
I want the UIImageView to adapt itself to the dimensions of the image it contains with the constraint that the width of the image view shouldn't exceed a maximal width size (in my case, 312px).
I set up the 'autosizing' configuration of my UIImageView to have a fixed left, top and right margin size. Nevertheless, when I call sizeToFit on my UIImageView and its image is larger than 352px, the UIImageView gets wider than its containing UIView.
Is there a convenient method to prevent such a behavior without doing the math based on the image dimensions? Am I using sizeToFit the right way?
Just use setClipsToBounds:
[imageView setClipsToBounds:YES];

Resources