Unable to programatically align UIImageView to the centre of UICollectionViewCell - ios

Currently, I have a UICollectionViewCell used in horizontal scroll UICollectionView. I have tried the following to centre the icon to the centre.
class BasicCell: UICollectionViewCell {
var tabInfo: TabInfo?
let imageView: UIImageView = {
let image = UIImage(systemName: "gear")
let imageView = UIImageView(image: image)
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(imageView)
// Hoping we can center imageView. But it would not work? Why?
addConstraint(NSLayoutConstraint.init(item: imageView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: 0))
addConstraint(NSLayoutConstraint.init(item: imageView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0))
BasicCell.topRoundCorners(self.contentView)
}
Here's the outcome
I expect the following code can centre the UIImageView without issue. However, it doesn't help
addConstraint(NSLayoutConstraint.init(item: imageView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: 0))
addConstraint(NSLayoutConstraint.init(item: imageView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0))
At first, I was thinking to give up the programatically way, and create UI layout via storyboard. However, in my storyboard, there is no UICollectionViewController. (The top tab bar component, is a UIView holding a UICollectionView created programatically).
Without UICollectionViewController, I don't find a way to drag and drop a UICollectionViewCell into the storyboard.
Do you have any idea, how I can centre my UIImageView, with correct programatically code? Or, should I try to fix this problem with XIB? Thanks.

by default, the UIView create programaticly has translatesAutoresizingMaskIntoConstraints = true, change it to false to enable auto layout :
imageView.translatesAutoresizingMaskIntoConstraints = false
let iamgeViewConstraints = [
imageView.centerXAnchor.constraint(equalTo: centerXAnchor),
imageView.centerYAnchor.constraint(equalTo: centerYAnchor)
]
NSLayoutConstraint.activate(iamgeViewConstraints)

Try to set imageView.translatesAutoresizingMaskIntoConstraints = false that tells iOS not to create auto layout constraints programmatically. Also, you can set constraints using frame like
imageView.frame = CGRect(x: superView.frame.width / 2, y: superView.frame.height / 2, width: imageViewWidth, height: imageViewHeight)
then you don't require imageView.translatesAutoresizingMaskIntoConstraints = false

Related

Swift: Unable to addConstraint to ImageView

I am adding an UberLogo on my app's menu bar using ImageView. However, the logo is paned towards the upper left corner of the cell. I tried to re-center it to its containing cell using an online video. The addConstraintWithFormat is working but not the add Constraint. Can anyone help? Thank you!
class MenuCell: BaseCell {
let imageView: UIImageView = {
let iv = UIImageView()
iv.image = UIImage(named: "UberLogo")
return iv
}()
override func setupViews() {
super.setupViews()
addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
addConstraintsWithFormat("H:|[v0(28)]|", views: imageView)
addConstraintsWithFormat("V:|[v0(28)]|", views: imageView)
addConstraint(NSLayoutConstraint(item: imageView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: 0))
addConstraint(NSLayoutConstraint(item: imageView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0))
}
}
As per the addConstraint documentation:
When developing for iOS 8.0 or later, set the constraint’s isActive property to true instead of calling the addConstraint(_:) method directly. The isActive property automatically adds and removes the constraint from the correct view.
Additionally, NSLayoutConstraint has the following function:
class func activate(_ constraints: [NSLayoutConstraint])
Try activating your constraints like this and see if it helps:
addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
imageView.heightAnchor.constraint(equalToConstant: 28),
imageView.widthAnchor.constraint(equalToConstant: 28),
imageView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
imageView.centerYAnchor.constraint(equalTo: self.centerYAnchor)
])

Why does my button change padding in the iOS simulator?

I am trying to add a button to a view in my iOS app. In the Main.storyboard file the button appears as this:
However, whenever I start the simulator the button appears as:
If it helps, I have the button paired to a custom class that consists of:
import UIKit
class RoundedButton: UIButton {
override func awakeFromNib() {
super.awakeFromNib()
layer.borderWidth = 1
layer.borderColor = UIColor.blue.cgColor
contentEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
}
}
But I do not believe this is the cause of the issue. I think the problem stems from my lack of understanding of how scaling works in xCode but I am unable to find any resources on how to fix this issue.
Thanks!
Add constraints to your button and check. It will be perfect if you add the necessary constraints.
Constraints are used to tell devices where objects should be and their sizes, even with different devices, you can create a pattern. Remember you always have to configure X, Y, width and height so your elements are placed perfectly. Except for labels, which sometimes doesn't require width and height constraints.
For your button, adding constraints to align horizontally, vertically, width and height should work.
Add necessary constraints for the button. you can add in storyboard or programmatically.
In storyboard, you can add constraints like this:
For programmatically:
let horConstraint = NSLayoutConstraint(item: yourButton!, attribute: .centerX, relatedBy: .equal,
toItem: view, attribute: .centerX,
multiplier: 1.0, constant: 0.0)
let verConstraint = NSLayoutConstraint(item: yourButton!, attribute: .centerY, relatedBy: .equal,
toItem: view, attribute: .centerY,
multiplier: 1.0, constant: 0.0)
let widConstraint = NSLayoutConstraint(item: yourButton!, attribute: .width, relatedBy: .equal,
toItem: view, attribute: .width,
multiplier: 0.95, constant: 0.0)
let heiConstraint = NSLayoutConstraint(item: yourButton!, attribute: .height, relatedBy: .equal,
toItem: view, attribute: .height,
multiplier: 0.95, constant: 0.0)
view.addConstraints([horConstraint, verConstraint, widConstraint, heiConstraint])

ClipsToBounds is not working in cells

I have an UITableView with custom cells. The structure of every cell is like that: I have contentView, in this contentView I have backView (simple UIView with white background and cornered radius 16.0), in this backView I have an imageView with some picture.
What I want is to have this imageView cornered (within his parent UIView — backView — borders). And it doesn't work this way.
The code is quite simple (from ImageCell.swift):
self.backView = UIView()
self.backView.backgroundColor = UIColor.white
self.backView.translatesAutoresizingMaskIntoConstraints = false
self.backView.layer.cornerRadius = 16.0
self.contentView.addSubview(backView)
self.picture = UIImageView()
self.picture.translatesAutoresizingMaskIntoConstraints = false
self.picture.contentMode = UIViewContentMode.scaleAspectFill
self.picture.backgroundColor = UIColor.gray
self.picture.clipsToBounds = true
self.backView.addSubview(picture)
let constraintPicTop = NSLayoutConstraint(item: picture, attribute: .top, relatedBy: .equal, toItem: contentView, attribute: .topMargin, multiplier: 1.0, constant: -6)
let constraintPicLeft = NSLayoutConstraint(item: picture, attribute: .left, relatedBy: .equal, toItem: backView, attribute: .leftMargin, multiplier: 1.0, constant: -8)
let constraintPicRight = NSLayoutConstraint(item: picture, attribute: .right, relatedBy: .equal, toItem: backView, attribute: .rightMargin, multiplier: 1.0, constant: 8)
constraintBottomPic = NSLayoutConstraint(item: picture, attribute: .bottom, relatedBy: .lessThanOrEqual, toItem: contentView, attribute: .topMargin, multiplier: 1.0, constant: 150)
I don't know the size of the image beforehand, so constraintBottomPic value is updating in cellForRowAt function.
And it's working except this image is not cornered (and I believe it should be).
(It's not possible for me to set cornerRadius for UIImageView unfortunately).
update: Found the solution. It seems I had to set 'clipsToBounds' to true in all the parent views directly (contentView and backView, in my case).
You should set the clipsToBounds property of the higher level container view (like the contentView of your cell.)
Apply imageView.layer.maskToBounds = YES;
Apply this to view or imageview on which you want to set corner radius.
As you have mentioned corner radius to your view you need to set this for your view

Constraints were ignored when trying to implement constraints programmatically

I'm trying to center a logoImage horizontally & vertically by setting constraints but when tested, It was displayed on (x:0, y:0).
Any idea how to fix this?
Thanks
var movieView : UIView?
let logoImage = UIImageView(image: #imageLiteral(resourceName: "my_logo"))
// This function runs in viewWillAppear
internal func setupIntroMovie() {
movieView = UIView(frame: view.frame)
view.addSubview(movieView!)
view.addSubview(logoImage)
let horizontalConstraint = NSLayoutConstraint(item: logoImage,
attribute: .centerX,
relatedBy: .equal,
toItem: view,
attribute: .centerX,
multiplier: 1,
constant: 0)
let verticalConstraint = NSLayoutConstraint(item: logoImage,
attribute: .centerY,
relatedBy: .equal,
toItem: view,
attribute: .centerY,
multiplier: 1,
constant: 0)
view.addConstraints([horizontalConstraint,
verticalConstraint])
updateViewConstraints()
}
You need to set logoImage.translatesAutoresizingMaskIntoConstraints = false as it determines whether the view’s autoresizing mask is translated into Auto Layout constraints.
internal func setupIntroMovie() {
movieView = UIView(frame: view.frame)
view.addSubview(movieView!)
view.addSubview(logoImage)
let horizontalConstraint = NSLayoutConstraint(item: logoImage,
attribute: .centerX,
relatedBy: .equal,
toItem: view,
attribute: .centerX,
multiplier: 1,
constant: 0)
let verticalConstraint = NSLayoutConstraint(item: logoImage,
attribute: .centerY,
relatedBy: .equal,
toItem: view,
attribute: .centerY,
multiplier: 1,
constant: 0)
// Update
logoImage.translatesAutoresizingMaskIntoConstraints = false
view.addConstraints([horizontalConstraint,
verticalConstraint])
updateViewConstraints()
}
If this property’s value is true, the system creates a set of
constraints that duplicate the behavior specified by the view’s
autoresizing mask. This also lets you modify the view’s size and
location using the view’s frame , bounds , or center properties,
allowing you to create a static, frame-based layout within Auto
Layout.

Using Autolayout Constraints programmatically to center a UIImageView inside a UIView Swift 2.3 iOS10

I have added a UIView to a table cell through my storyboard with the following constraints:
Then I have the following code to programmatically add a UIImageView to the UIView above and size it according to the orientation of the screen.
//Use half the screen size width when on an iPhone and on Landscape
let image: UIImage = UIImage(named: HEADER_IMAGE_BATH)!
imageView = UIImageView(image: image)
imageView!.frame = CGRectMake(0 , 0, self.view.frame.width / 2, 185)
imageView!.contentMode = .ScaleAspectFit
//center image
let centerXConst = NSLayoutConstraint(item: imageView!, attribute: .CenterX, relatedBy: .Equal, toItem: imageWrapperView, attribute: .CenterX, multiplier: 1, constant: 1)
let centerYConst = NSLayoutConstraint(item: imageView!, attribute: .CenterY, relatedBy: .Equal, toItem: imageWrapperView, attribute: .CenterY, multiplier: 1, constant: 1)
NSLayoutConstraint.activateConstraints([centerXConst, centerYConst])
//add to sub view
imageWrapperView.addSubview(imageView!)
However, my image does not get centered when in landscape. My image is only half the width of the screen and I would like to center it inside my UIView. What am I missing? Thanks
You should use Auto Layout instead of frame for width and height of imageView
You have to add imageView to imageWrapperView before add constraints
You have to set imageView.translatesAutoresizingMaskIntoConstraints to false
Then, the final code is:
//Use half the screen size width when on an iPhone and on Landscape
let image: UIImage = UIImage(named: "key.png")!
let imageView = UIImageView(image: image)
imageView.contentMode = .ScaleAspectFit
imageView.translatesAutoresizingMaskIntoConstraints = false
//add to sub view
imageWrapperView.addSubview(imageView)
//center image
let centerXConst = NSLayoutConstraint(item: imageView, attribute: .CenterX, relatedBy: .Equal, toItem: imageWrapperView, attribute: .CenterX, multiplier: 1.0, constant: 0.0)
let centerYConst = NSLayoutConstraint(item: imageView, attribute: .CenterY, relatedBy: .Equal, toItem: imageWrapperView, attribute: .CenterY, multiplier: 1.0, constant: 0.0)
let heightConstraint = NSLayoutConstraint(item: imageView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 185.0)
let widthConstraint = NSLayoutConstraint(item: imageView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: self.view.frame.width / 2)
imageView.addConstraints([heightConstraint, widthConstraint])
NSLayoutConstraint.activateConstraints([centerXConst, centerYConst])
When you're using autolayout, do not try to change the frame of the views. If you need to change the frame, better take the outlets of the constraints and change them programatically.
In your question, to center align the imageView, you can do it by putting 4 constraints. Set the height and width of the imageView and the other two are center horizontally and center vertically constraints.
This is the basic way of center aligning any type of view.

Resources