我想通过修改约束属性(如topAnchor)将UIView boardGame: UICollectionView的位置移动到屏幕中央,但我对它所做的任何操作似乎都会影响它内部的内容.我还定义了UICollectionViewCell模型,这样我就可以将boardGame中的单元注册为"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)
        }
    
}

以下是CustomCollectionViewCell: UICollectionViewCell的型号:

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")
    }
}

以及接收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)
    }
}

我试过在boardGamein topAnchorin constant: CGFloat的属性上做手脚.给出一些背景,这里是一个例子,我得到了boardGame.topAnchor.constraint(equalTo: view.topAnchor, constant: 20)

enter image description here

如果我将CGFloat更改为200以使其更居中,则它内部CustomCollectionViewCell的属性将移动到边缘,影响上边距,如下所示:

enter image description here

我已经试图弄乱CustomCollectionViewCell内部的titleLabel个最上面的constraint个边距,但似乎什么都不做.

我如何才能在不影响CustomCollectionViewCell的边距的情况下将boardGame的视图保持在中心位置?

推荐答案

单元格位于集合视图的顶部边缘,因为.这是精心设计的.当集合视图位于屏幕顶部时,单元格只有appear个"居中",因为默认情况下,单元格的布局是为了避开安全区(在本例中为动态孤岛).

在任何情况下,你的限制都是相互矛盾的.您是说boardGame视图应该有固定的宽度和高度(假设SuperView的宽度和高度是固定的),它的中心点应该与SuperView的中心点(centerX = view.centerXcenterY = view.centerY)相同,and它的顶部距离SuperView的顶部只有20个点.

这些都不可能同时得到满足.正如您在第一个屏幕截图中看到的,centerY = view.centerY约束被打破,以满足其他约束.

如果希望集合视图在垂直和水平方向上都居中,只需取消上边距限制:

boardGame.topAnchor.constraint(equalTo: view.topAnchor, constant: margin)

如果还希望单元格垂直居中,可以设置contentOffset:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    boardGame.contentOffset.y = (boardGame.contentSize.height - boardGame.bounds.height) / 2
}

也就是说,如果boardGame不应该是可滚动的,那么可以考虑使用一系列UIStackView来进行这种布局.示例:

class BoardViewController: UIViewController {
    
    var boardGame: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        func makeCell(color: UIColor) -> Cell {
            let cell = Cell(frame: .zero)
            cell.backgroundColor = color
            return cell
        }
        
        func makeColumn(_ views: [UIView]) -> UIStackView {
            let col = UIStackView(arrangedSubviews: views)
            col.axis = .vertical
            col.spacing = 8
            col.alignment = .center
            col.distribution = .fillEqually
            return col
        }
        let col1 = makeColumn([makeCell(color: .black), makeCell(color: .black), makeCell(color: .black)])
        let col2 = makeColumn([makeCell(color: .white), makeCell(color: .white), makeCell(color: .white)])
        let col3 = makeColumn([makeCell(color: .black), makeCell(color: .black), makeCell(color: .black)])
        let columns = UIStackView(arrangedSubviews: [col1, col2, col3])
        columns.axis = .horizontal
        columns.spacing = 16
        columns.distribution = .fillEqually
        columns.translatesAutoresizingMaskIntoConstraints = false
        
        boardGame = UIView()
        boardGame.backgroundColor = .gray
        boardGame.addSubview(columns)
        boardGame.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(boardGame)
        NSLayoutConstraint.activate([
            columns.topAnchor.constraint(equalTo: boardGame.topAnchor, constant: 20),
            columns.bottomAnchor.constraint(equalTo: boardGame.bottomAnchor, constant: -20),
            columns.leftAnchor.constraint(equalTo: boardGame.leftAnchor, constant: 8),
            columns.rightAnchor.constraint(equalTo: boardGame.rightAnchor, constant: -8),
            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),
        ])
    }
    
}

class Cell: UIView {
    
    let titleLabel = UILabel()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        addSubview(titleLabel)
        
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        titleLabel.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        titleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
        titleLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
        titleLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        
        self.translatesAutoresizingMaskIntoConstraints = false
        self.widthAnchor.constraint(equalTo: self.heightAnchor).isActive = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Swift相关问答推荐

为什么第二项任务不在第一项任务完成之前开始?(并发队列)

向文本元素添加背景色失败

通过SwiftUI中的列表 Select 从字典中检索值

了解SWIFT中的任务行为

UICollectionViewCompostionalLayout Collectionview单元格宽度在重新加载数据后未正确调整大小

expose 不透明的底层类型

是否可以限制 ExpressibleByIntegerLiteral struct 的初始值?

Swift Random Float Fatal Error:在无限范围内没有均匀分布

在 SwiftUI 中将属性显式设置为其默认值

签署GoogleSignIn-GoogleSignIn需要开发团队

如何处理永远不会失败的 String.Encoding 初始化程序?

`IndexSet` 永远不会是空的?

Vapor Swift 如何配置客户端连接超时

Swift - 如何更新多目录中的对象

在 Swift 4 中实现自定义解码器

swift 3 错误:参数标签 '(_:)' 不匹配任何可用的重载

关闭 UITableViewRowAction

如何为多个类 Swift 进行扩展

自定义 MKAnnotation 标注视图?

Facebook SDK 4.0 IOS Swift 以编程方式注销用户