首先,您不需要将框架设置为显式值...使用约束并让自动布局为您完成所有工作。
其次,如果你希望你的collectionView是Square,当视图的高度很短时它会变得非常小——比如手机旋转到横向:
这是获取该布局的示例代码:
class GameViewController: UIViewController, UICollectionViewDataSource {
let stack: UIStackView = {
let v = UIStackView()
v.axis = .vertical
v.alignment = .fill
v.distribution = .fill
v.spacing = 0
return v
}()
let gameContainerView = UIView()
let secondView = UIView()
var theCollection: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: 50, height: 50)
layout.minimumLineSpacing = 4
layout.minimumInteritemSpacing = 4
theCollection = UICollectionView(frame: .zero, collectionViewLayout: layout)
theCollection.translatesAutoresizingMaskIntoConstraints = false
stack.addArrangedSubview(gameContainerView)
stack.addArrangedSubview(secondView)
stack.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stack)
// respect safe area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// constrain stack view to fill safe area
stack.topAnchor.constraint(equalTo: g.topAnchor),
stack.leadingAnchor.constraint(equalTo: g.leadingAnchor),
stack.trailingAnchor.constraint(equalTo: g.trailingAnchor),
stack.bottomAnchor.constraint(equalTo: g.bottomAnchor),
// second view always has a height of 150
secondView.heightAnchor.constraint(equalToConstant: 150.0),
])
// add collection view to game container view
gameContainerView.addSubview(theCollection)
NSLayoutConstraint.activate([
// it looks like you want the collection view to be square (1:1 ratio)
// as large as possible
// with 23-pts on top/bottom or left/right, whichever is needed
// give it a 1:1 ratio
theCollection.heightAnchor.constraint(equalTo: theCollection.widthAnchor),
// centered in container view
theCollection.centerXAnchor.constraint(equalTo: gameContainerView.centerXAnchor),
theCollection.centerYAnchor.constraint(equalTo: gameContainerView.centerYAnchor),
// we need *at least* 23-pts "padding"
theCollection.topAnchor.constraint(greaterThanOrEqualTo: gameContainerView.topAnchor, constant: 23.0),
theCollection.leadingAnchor.constraint(greaterThanOrEqualTo: gameContainerView.leadingAnchor, constant: 23.0),
theCollection.trailingAnchor.constraint(lessThanOrEqualTo: gameContainerView.trailingAnchor, constant: -23.0),
theCollection.bottomAnchor.constraint(lessThanOrEqualTo: gameContainerView.bottomAnchor, constant: -23.0),
])
// we also need to constrain the collection view's
// Height and Width equal to the container's Height and Width
// but with Priority less than Required
let w = theCollection.widthAnchor.constraint(equalTo: gameContainerView.widthAnchor)
let h = theCollection.heightAnchor.constraint(equalTo: gameContainerView.heightAnchor)
w.priority = .defaultHigh
h.priority = .defaultHigh
w.isActive = true
h.isActive = true
// set background colors so we can easily see the frames
theCollection.backgroundColor = .cyan
gameContainerView.backgroundColor = .green
secondView.backgroundColor = .yellow
theCollection.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
theCollection.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 42
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
cell.backgroundColor = .blue
return cell
}
}