I want to move the position of a UIView boardGame: UICollectionView to be on the center of the screen by modifying the constraints properties such as topAnchor, but anything I do to it seems to affect the content inside of it. I have also defined a UICollectionViewCell model so I can be register the cells in boardGame as "uinique".
import UIKit
class BoardViewController: UIViewController {
private let boardGame: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let board = UICollectionView(frame: .zero, collectionViewLayout: layout)
board.allowsSelection = true
board.register(CustomCollectionViewCell.self, forCellWithReuseIdentifier: "unique")
board.translatesAutoresizingMaskIntoConstraints = false
return board
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(boardGame)
boardGame.backgroundColor = .systemGray2
boardGame.frame = view.bounds
let margin: CGFloat = 20
NSLayoutConstraint.activate([
boardGame.topAnchor.constraint(equalTo: view.topAnchor, constant: margin),
boardGame.centerXAnchor.constraint(equalTo: view.centerXAnchor),
boardGame.centerYAnchor.constraint(equalTo: view.centerYAnchor),
boardGame.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -20),
boardGame.heightAnchor.constraint(equalTo: view.widthAnchor, constant: -20),
])
boardGame.delegate = self
boardGame.dataSource = self
}
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension BoardViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 9
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "unique", for: indexPath) as! CustomCollectionViewCell
let chessRow = indexPath.row / 3
if chessRow % 2 == 0 {
if indexPath.row % 2 == 0 {
cell.backgroundColor = UIColor.white
}else{
cell.backgroundColor = UIColor.black
}
} else{
if indexPath.row % 2 == 0 {
cell.backgroundColor = UIColor.black
}else{
cell.backgroundColor = UIColor.white
}
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// Divide the width by 3 to create a 3x3 grid
let width = collectionView.frame.size.width / 4.0
let height = width
return CGSize(width: width, height: height)
}
}
Here is the CustomCollectionViewCell: UICollectionViewCell model:
class CustomCollectionViewCell: UICollectionViewCell {
let titleLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(titleLabel)
titleLabel.translatesAutoresizingMaskIntoConstraints = false
titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
And the parent view that receives the instance of the BoardViewController
import UIKit
class MainViewController: UIViewController {
let boardView = BoardViewController()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
addBoardView()
}
func addBoardView(){
addChild(boardView)
view.addSubview(boardView.view)
boardView.didMove(toParent: self)
}
}
I have tried playing around with the properties of the constant: CGFloat in topAnchor in boardGame. To give some context here is an example of what I get with boardGame.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
If I change the CGFloat to 200 to make it more centered the properties of the CustomCollectionViewCell inside it moved to the edged afecting the top margin like so:
I already tried to mess with the titleLabel top margin constraint inside of CustomCollectionViewCell but does not seem to do anything.
How could I keep the boardGame view in the center without affecting the margin of CustomCollectionViewCell?


The cells are positioned at the top edge of the collection view, because that's how collection views work. This is by design. The cells only appear "centred", when the collection view is at the top of the screen, because the cells are laid out to avoid the safe area (the dynamic island in this case) by default.
In any case, your constraints are contradictory. You are saying that the
boardGameview should have a fixed width and height (assuming the superview's width and height are fixed), and its centre point should be the same as the superview's centre point (centerX = view.centerXandcenterY = view.centerY), and its top is only 20 points away from the superview's top.These cannot all be satisfied simultaneously. As you can see in the first screenshot, the
centerY = view.centerYconstraint is broken, to satisfy the other constraints.If you want the collection view to be centred both vertically and horizontally, just remove the top margin constraint:
If you also want the cells to be centred vertically, you can set
contentOffset:That said, if
boardGameis not supposed to be scrollable, consider using a series ofUIStackViews for this layout instead. Example: