Empty space in UIImageView when using scaleAspectFit - ios

Here is an image of my issue. My problem is that I have an tiny empty space on the right side of my UIImageView that is constrained to the view of my view controller. It's green because of the background I set, and it is more prominent on my device. It's weird because the image should fit the whole screen considering the image was taken on the phone itself and I am using scaleAspectFit.
let imageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.isUserInteractionEnabled = true
imageView.contentMode = .scaleAspectFit
imageView.backgroundColor = .green
imageView.clipsToBounds = true
return imageView
}()
Here is the code for the constraints:
func setupImageView() {
self.view.addSubview(imageView)
let imageViewConstraints = [
imageView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
imageView.topAnchor.constraint(equalTo: self.view.topAnchor),
imageView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
imageView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)
]
NSLayoutConstraint.activate(imageViewConstraints)
}
I am basically setting the image using self.imageView.image and I end up with a empty space on the right side that is only noticeable when using bright colors as the imageView background. Not sure if this is a bug. The only reason I'm not using fill is because I want to maintain the aspect while showing the whole image.

The contentMode scaleAspectFit will keep the scale of the image, display the whole content of the image. Because your photo scale is same to the screen, if your imageView height is less than screen, the image display width will be less than screen too, which causes the background green color shows.
To ensure the imageView fits the screen, you can add border on it:
imageView.layer.borderColor = UIColor.red.cgColor
imageView.layer.borderWidth = 1.0

Try to use in your imageView{
imageView.contentMode = .scaleAspectFill
}

Related

Understanding layout anchors in Swift

So, I have this ViewController where I render an image inside a subview.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
let childView = UIView()
childView.backgroundColor = .red
let imageView = UIImageView(image: UIImage(systemName: "tray"))
imageView.contentMode = .scaleAspectFill
childView.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
imageView.heightAnchor.constraint(equalToConstant: 100.0)
])
view.addSubview(childView)
childView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
childView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor)
])
}
}
As you can see for some reason, the image moves to the left of screen. What is the cause of that?
One more thing I noticed is the subview should have a background color of red as specified, but somehow it's transparent. Why is that?
I expect the result to be something like,
You are adding way too few constraints. The horizontal position and size of the childView are not constrained at all, so the size just defaults to (0, 0), making the view not visible at all, which is why you don't see the red background.
First, let's constrain the horizontal position. This seems to be what you intended:
NSLayoutConstraint.activate([
// wouldn't it be better to use safeAreaLayoutGuide?
childView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
childView.leftAnchor.constraint(equalTo: view.layoutMarginsGuide.leftAnchor)
])
Then, the size of the childView should be the same as the imageView, so you should activate these constraints too:
imageView.leftAnchor.constraint(equalTo: childView.leftAnchor),
imageView.rightAnchor.constraint(equalTo: childView.rightAnchor),
imageView.topAnchor.constraint(equalTo: childView.topAnchor),
imageView.bottomAnchor.constraint(equalTo: childView.bottomAnchor),
There is one more thing though - the size of the image view at this point is not what you expect. The image view has a height of 100, but its width is still 24, which is the intrinsic size of the "tray" image. scaleAspectFill does scale the image to the size you want, but the views' widths stay at 24, and since the scaling is done from the centre of the view, the scaled up image appears to be "off centred".
I think that in general, you'll just have to manually calculate the width you want:
let width = 100 * image.size.width / image.size.height
and constrain both width and height:
imageView.heightAnchor.constraint(equalToConstant: 100.0),
imageView.widthAnchor.constraint(equalToConstant: width),
However, with SF symbols, you can get a bigger image simply by:
let image = UIImage(systemName: "tray", withConfiguration: UIImage.SymbolConfiguration(pointSize: 100))
You don't need any height or width constraints on the image view.

How to resize image in UIView?

I tried to set image into UIView but I can't resize it in my view I got something like this:
UIview
let imageName = "rectanguloAzul"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.contentMode = .scaleAspectFill
self.view.addSubview(imageView)
Welcome.
You need to either give the imageView a frame or use Autolayout to set a layout for the image inside the UIView.
so either add this at the end:
imageView.frame = view.frame
But this will not be dynamic and you should learn how to keep updating the frame whenever the superview's frame changes.
Or you can add this, instead:
imageView.translatesAutoresizingMaskIntoConstraints = false
let constraints = [
imageView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor),
imageView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor),
imageView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor),
imageView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor)
]
NSLayoutConstraint.activate(constraints)
Anyway, I really recommend you read up about AutoLayout a bit before you continue:
https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/index.html
https://www.raywenderlich.com/811496-auto-layout-tutorial-in-ios-getting-started
If you find programmatic AutoLayout to be too challenging, I would recommend possibly starting with Storyboards first.

Centering an UIImage (horizontally or vertically) with programatic constraints UIKit

I am trying to simply center a 5x5 image in a horizontal row in UIKit.
On the left of the view I have a UIView that has its left and top margins attached to the parent view and has intrinsic width and height. It might not exactly fill half of the containing view (so assume its width is arbitrary).
To the right of it (but on the same row) I am trying to put a UIImage that is centered in the blank space to the right of the left object. Meaning it is both centered horizontally and vertically but to the right of the other object.
I really have no clue how to accomplish this although I figure there are both more and less elegant ways to achieve this.
After you set a proper width and height for it set these constraints
smallView.centerYAnchor.constraint(equalTo: greenView.centerYAnchor).isActive = true
smallView.centerXAnchor.constraint(equalTo: parentView.centerXAnchor, multiplier:1.5).isActive = true
It's pretty simple. You'll use a layout guide to define the beginning and end of the horizontal space. Then you'll center your view in the layout guides center. I have included layoutMarginsGuide which can be adjusted by setting container.layoutMargins.
let containerView = UIView()
containerView.backgroundColor = .gray
// Add view to parent ...
let greenView = UIView()
greenView.translatesAutoresizingMaskIntoConstraints = false
greenView.backgroundColor = .green
containerView.addSubview(greenView)
greenView.topAnchor.constraint(equalTo: containerView.layoutMarginsGuide.topAnchor).isActive = true
greenView.leadingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.leadingAnchor).isActive = true
let horizontalGuide = UILayoutGuide()
containerView.addLayoutGuide(horizontalGuide)
horizontalGuide.leadingAnchor.constraint(equalTo: greenView.trailingAnchor, constant: containerView.layoutMargins.left).isActive = true
horizontalGuide.trailingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.trailingAnchor).isActive = true
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.backgroundColor = .red
containerView.addSubview(imageView)
imageView.centerXAnchor.constraint(equalTo: horizontalGuide.centerXAnchor).isActive = true
imageView.centerYAnchor.constraint(equalTo: greenView.centerYAnchor).isActive = true

iOS - Set ImageView background color and mask

How can I set the background color of an ImageView for an icon and have it mask to bounds? So that the inner transparent parts of the image are then the background color?
Example: in this twitter icon, how can I set the inner white (transparent) parts of the icon to be a different color?
EDIT: What if the image is NOT a circle? But any shape.
You have to follow the following steps
imageView.image = UIImage(named: "yourImageName")?.withRenderingMode(.alwaysOriginal)
imageView.layer.cornerRadius = 14 //number of your choice
imageView.layer.masksToBounds = true
imageView.tintColor = .black
imageView.backgroundColor = .blue //Sets the background color
imageView.layer.cornerRadius = imageView.width/2 //Crops the image to be a circle
imageView.layer.masksToBounds = true //Sets the mask to bounds
If you want a custom shape you can do this:
create two imageViews (above each other)
first imageView use as usual
second imageView use as background shape
Code for the one in foreground
firstImageView.backgroundColor = .clear
Second imageView (in the background)
secondImageView.image = UIImage(named: "yourImage").withRenderingMode(.alwaysTemplate)
secondImageView.tintColor = yourBackgroundColor
secondImageView.backgroundColor = .clear

rounded imageView 's border is not smooth after setting image property

class PPAvatarCollectionCell: UICollectionViewCell {
var imageView:UIImageView!
override init(frame: CGRect) {
super.init(frame: frame)
imageView = UIImageView(frame: CGRect(origin: CGPointMake(0, 0), size: CGSizeMake(frame.size.width, frame.size.height)))
self.addSubview(imageView)
imageView.contentMode = .ScaleAspectFill
imageView.backgroundColor = UIColor.whiteColor()
imageView.layer.borderColor = UIColor.greenColor().CGColor
imageView.layer.borderWidth = 10
imageView.image = UIImage(named: "demo")
imageView.layer.cornerRadius = frame.size.width*0.5
imageView.clipsToBounds = true
}
the border is smooth and great with above code
but after add imageView.image = UIImage(named: "demo")
the imageView's border is no longer smooth.
Why did this happen ?
UPDATE:
Seems something wrong with layer.radius ,the border is smooth even with image property set on imageView after remove imageView.layer.cornerRadius = frame.size.width*0.5
UPDATE 2:
turn out to be something wrong with UICollectionViewCell , imageView is a part of UICollectionViewCell
u can use 2 imageview 1 to show image and second to hide and show circular image.
1st imageview show image as it is.
2nd imageview which will have white background and green circle above 1st image and middle of image will be transparent
Basically, your image should be a square. Than do these:
imageView.layer.cornerRadius = self.frame.height / 2
imageView.layer.masksToBounds = false
imageView.clipsToBounds = true
imageView.image = "yourSquareImage"
Check the full solution with easy using extension:
https://stackoverflow.com/a/36102901/2125010

Resources