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,
CodePudding user response:
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.