Why UIImageView's image can extend beyond itself? - ios

Previously, i thought UIImageView's image cannot extend beyond the view. However, recently i read the book Programming in IOS8, it says:
You should also pay attention to a UIImageView’s clipsToBounds property; if it is false, its image, even if it is larger than the image view and even if it is not scaled down by the contentMode, may be displayed in its entirety, extending beyond the image view itself.
And then i did some simple test, that's true.
Here is the question: What's the purpose for Apple to design UIImageView with this feature? I, for now, cannot find the advantage of it. I think this makes contentMode a fake property.
Here is an example:
It is a refreshView with customized pull-to-refresh animation above in a UITableView. I set up a UIImageView with the same size as the refreshView and add it as a background view. Relevant code here:
let imgView = UIImageView()
imgView.frame = self.bounds
imgView.image = UIImage(named: "refresh-view-bg.png")
imgView.contentMode = .ScaleAspectFill
imgView.clipsToBounds = true
self.addSubview(imgView)
It works fine:
However, when i annotate this line:
imgView.clipsToBounds = true
It turns like that:
The image extend beyond the UIImageView
ps: I'm not using autoLayout in this demo

This is due to autolayout. UIImageView returns its -intrinsicContentSize by the calculation of image size. If you want to avoid that you should set a width (or height) constraints, or play with content hugging/compression resistance priorities if you want to share or not the space when you view is laid out with other views around.

Related

How to properly set the ContentMode of an ImageView within a UIView?

I am trying to set the contentMode of a UIImageView to be .top, that is contained within a UIView, but it's not set properly or runs out of the boundary of the UIView.
This is what my cell looks like with the red being the container UIView with constraints of the UIImageView:
FYI: The UIImageView is a square size because it will be applied with rounded corners.
What I've attempted to do and the result:
1.
thumbnail.contentMode = .top
thumbnail.clipsToBounds = true
thumbnail.sizeToFit()
2.
thumbnail.contentMode = .top
thumbnail.clipsToBounds = true
also tried adding:
thumbnailContainer.clipsToBounds = true
thumbnailContainer.sizeToFit()
What I'm trying to achieve is the result of the first screenshot with the UIImageView contained inside its container view as seen in the second screenshot.
UPDATE:
Based on the comments and answer, I believe some are confused on what exactly I'm trying to do, so I've attached another screenshot of the result I'm expecting :
As you can see, I want the contentMode of the UIImageView to be .top such that the top-middle of the image is displayed. You can clearly see the difference between the contentMode in the 3rd screenshot, which is .scaleAspectFit, versus the contentMode in the 4th screenshot, which is .top because it is showing the top-middle of the image.
However, I would like the UIImageView to maintain its original size, as seen in the 3rd screenshot where the contentMode is .scaleAspectFit, instead of being stretched out horizontally and vertically, as seen in the 2nd screenshot.
I hope this clarifies what I'm trying to achieve.
To achieve the result you want, you need to set content mode to .aspectFit, so that image will resize itself in UIImageView's size, keeping its original height to width ratio.

how to remove white space in circle UIImageView?

I wanted to circle my UIImageView and added this code :
profileImage.layer.cornerRadius = profileImage.frame.size.height/2
profileImage.clipsToBounds = true
and it work perfectly, but when images are horizontal, I get this picture:
as you can see, there is white space at the bottom and top of my circle image view. but what I really wanted was a circle filled with my image!
I've tried changing "content Mode" from attribute inspector, but I didn't get any answer! how can I fix this issue?
You have already set the clipsToBound property. So just update the contentMode.
I you don't want to distort image's scale:
profileImage.contentMode = .scaleAspectFill
If image's scale does not matter, you also can use:
profileImage.contentMode = .scaleToFill
Follow the link for more details: https://useyourloaf.com/blog/stretching-redrawing-and-positioning-with-contentmode/
Use below code:-
profileImage.clipsToBounds = true
profileImage.contentMode = .scaleAspectFill
Set the contentMode of your UIImageView to scaleAspectFill
profileImage.contentMode = .scaleAspectFill
Keep in mind that using this contentMode option some portion of the content may be clipped to fill the view’s bounds.
You can set the Different Content Mode as per you choice from StoryBoard:
You can select
Scale to Fill
Aspect Fill
or any other content mode by using trial and Error method which suits you
Hope it Helps.
If I choose Aspect Fit, I'm getting blank space in top and bottom of the imageview.
Can I trim that space anyhow?
Is there any programatically constraints I can set to re-scale imageview according to actual image size?

UIImageView not clipping to UIView bounds while animating

I have a UIImageView in a UICollectionViewCell that I am moving in relation to a scroll views content offset. This is all to provide a parallax effect when the user scrolls horizontally, however there seems to be a clipping issue when the scroll view begins to scroll.
Instead of clipping, the edges persist and are shown outside of the containers boundaries.
The attached screenshot best showcases the behavior...
In the screen shot the scroll view has begun scrolling right and the accompanying views have begun translating however the UIImageView has not clipped its borders to match the receiver. Which in this case should be the transparent UIView.
Here is the UIImageView
let cellImage: UIImageView = {
let c = UIImageView()
c.clipsToBounds = true
c.layer.masksToBounds = true
c.contentMode = .scaleAspectFill
c.image = UIImage(named: "tree")
c.translatesAutoresizingMaskIntoConstraints = false
c.layer.cornerRadius = 15
return c
}()
The UIImageView is then added to a containerView and is set to fill it's bounds.
cellContainerView.addSubview(cellImage)
//add constraints
My thoughts are that if anything this issue may have to do with my interpretation of what the .clipsToBounds property does.
The documentation states:
Setting this value to true causes subviews to be clipped to the bounds
of the receiver.
I initially thought the receiver was the view you attached the UIImageView to however that is looking to not be the case.
Any suggestions?
As the documentation states:
Setting this value to true causes subviews to be clipped to the bounds
of the receiver.
Currently you are setting this property on cellImage ,so in this case it is the receiver, so its subviews will be clipped. But you want to clip this imageview so I think you need to set this property on cellContainerView, since you want its subviews to be clipped.

When I click the cell, the image is stretch out

This is the cell I created by XIB:
But however, after I use tableView load the cells, I get the issue:
You need to change image scale as below :
imageView.contentMode = UIViewContentModeScaleAspectFit;
Swift 3
imageView.contentMode = .scaleAspectFit
It is because you used Aspect Fill in the attribute pannel. Thus the image width equal to the screen (as per your constraints) and keep its width*height ratio, but it is going outside bounds of your imageView.
You need to add in viewDidLoad or in your class file:
imageView.clipsToBounds = true
Check this link to Apple's documentations
you need to clip the image out side bounds:
imageView.clipsToBounds = YES
it will crop image to visible rect only
If you design your cell in xib, you can set the Clip to Bounds in Drawing:

How to add many UIImageViews inside ScrollView?

I will have about 12+ (any multiple of 4 per row) images that I want to have inside a ScrollView. See example below, the 12 circles (with the last row cut off a bit) are the UIImageViews.
I am not able to add the UIImageViews inside the ScrollView. The width,height of the scrollView is 250,250
This is what I have tried:
func setScrollView() {
scrollView_avatars.contentSize = CGSizeMake(250,300);
let imgView1: UIImageView = UIImageView(image: UIImage(named: "img1.jpg"))
let imgView2: UIImageView = UIImageView(image: UIImage(named: "img2.jpg"))
let imgView3: UIImageView = UIImageView(image: UIImage(named: "img3.jpg"))
scrollView_avatars.addSubview(imgView1)
scrollView_avatars.addSubview(imgView2)
scrollView_avatars.addSubview(imgView3)
}
iOS noob here
My code above gives me very bizarre output, i think the sizes of the UIImageViews are not set correctly.
I dont also know how to position the UIImageViews within the ScrollView like only part of a image is visible.
As #rmaddy says, you need to set the frame properties on your views. You will need to do math to calculate their positions based on row/column position in your grid of views.
If you're using AutoLayout you may need to generate constraints to set the view's sizes and positions. (I haven't tried to add views to a scroll view in code with AutoLayout before, so I'm not totally positive what happens if you just set their frames without defining constraints.)
You need to declare your image views like this:
if let image = UIImage(named: "myImage"){
let imageView = UIImageView(frame: CGRectMake(yourXpoint, yourYpoint, image.size.width, image.size.height))
imageView.image = image
}
where yourXpoint and yourYpoint is where you want the image origin to be set, this way you are saying to swift where do you want the images to be place and what is its size.
The if let is just to be safe in case the image does not exist.
Another good option is to set constrains as it will make your app have a nice layout in al different screen sizes and orientation

Resources