提问人:willd 提问时间:10/21/2023 最后编辑:HangarRashwilld 更新时间:10/21/2023 访问量:23
以编程方式将 UIView 居中,而不影响其他 UI 类在 UIKit 中的位置
Center a UIView without affecting the position of other UI classes in UIKit programmatically
问:
我想通过修改约束属性(如 )将 UIView 的位置移动到屏幕的中心,但我对它所做的任何事情似乎都会影响其中的内容。我还定义了一个模型,这样我就可以将单元格注册为“uinique”。boardGame: UICollectionView
topAnchor
UICollectionViewCell
boardGame
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)
}
}
我试过玩弄in的属性。为了提供一些背景信息,这里是我得到的一个例子,constant: CGFloat
topAnchor
boardGame
boardGame.topAnchor.constraint(equalTo: view.topAnchor, constant: 20)
如果我将 200 更改为 200 以使其更居中,则内部的属性会移动到边缘,从而影响上边距,如下所示:CGFloat
CustomCollectionViewCell
我已经试图弄乱里面的上边距,但似乎什么也没做。titleLabel
constraint
CustomCollectionViewCell
我怎样才能在不影响边距的情况下将视图保持在中心?boardGame
CustomCollectionViewCell
答:
单元格位于集合视图的上边缘,因为这是集合视图的工作方式。这是设计使然。只有当集合视图位于屏幕顶部时,单元格才会显示为“居中”,因为默认情况下,单元格的布局会避开安全区域(在本例中为动态岛)。
无论如何,你的约束是矛盾的。您是说视图应该具有固定的宽度和高度(假设上视图的宽度和高度是固定的),并且其中心点应与上视图的中心点(和)相同,并且其顶部距离上视图的顶部仅 20 个点。boardGame
centerX = view.centerX
centerY = view.centerY
这些不能同时满足。正如您在第一个屏幕截图中看到的,为了满足其他约束,约束被破坏了。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
}
也就是说,如果不应该是可滚动的,请考虑为此布局使用一系列 s。例: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")
}
}
评论