swift - 分隔线出现早于单元格标题并且图像超出 UIImageView
问题描述
我以编程方式创建了 UITableView 和 Cell。一切正常,但我有几个关于约束和自动布局的问题:
带有 layoutMarginsGuide 的约束:
- 在宽度为 375 的屏幕中,下部分隔符和单元格从一个点开始。在大尺寸屏幕上,分隔符出现在单元格标题之前(您可以在随附的屏幕截图中看到)。我该如何解决这个问题?
- 所附屏幕截图中带有圆角的红色矩形的图像超出了 UIImageView。我向 UIImageView 添加了约束,但这对我没有帮助。我该如何解决这个问题?
没有 layoutMarginsGuide 的约束:
- 我希望 stackView 覆盖整个单元格。如何在不使用 layoutMarginsGuide 的情况下添加约束并避免控制台警告?
- 如何添加高度限制?我希望我的 stackView 或标题为 100 pt。
您可以在下面找到屏幕截图、单元格图标和代码。
感谢您的回答。
代码:
import Foundation
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// MARK: - Lifecycle Methods
override func viewDidLoad() {
super.viewDidLoad()
let tableViewstyle = UITableView.Style.insetGrouped
let tableView = UITableView(frame: CGRect(), style: tableViewstyle)
tableView.delegate = self
tableView.dataSource = self
tableView.register(Cell1.self, forCellReuseIdentifier: String(Cell1.description()))
tableView.tableFooterView = UIView()
tableView.translatesAutoresizingMaskIntoConstraints = false
self.view.backgroundColor = .systemBackground
self.view.addSubview(tableView)
NSLayoutConstraint.activate([
tableView.widthAnchor.constraint(equalTo: self.view.widthAnchor),
tableView.heightAnchor.constraint(equalTo: self.view.heightAnchor)
])
}
// MARK: - numberOfSections
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
// MARK: - numberOfRowsInSection
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 7
}
// MARK: - cellForRowAt
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: String(Cell1.description())) as! Cell1
cell.title.text = "Cell \(indexPath.row)"
cell.icon2.image = UIImage(named: "Icon")
return cell
}
}
// MARK: - Cell
class Cell1: UITableViewCell {
// MARK: - Properties
let title = UILabel()
let icon2 = UIImageView()
let stackView = UIStackView()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// Off translatesAutoresizingMaskIntoConstraints
title.translatesAutoresizingMaskIntoConstraints = false
icon2.translatesAutoresizingMaskIntoConstraints = false
stackView.translatesAutoresizingMaskIntoConstraints = false
// Set constraints
icon2.addConstraint(NSLayoutConstraint(item: icon2, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 30))
icon2.addConstraint(NSLayoutConstraint(item: icon2, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 30))
// StackView
stackView.axis = .horizontal
stackView.alignment = .center
stackView.distribution = .fill
// TitleAndDetailStackView
stackView.axis = .horizontal
stackView.alignment = .center
stackView.distribution = .fill
// Hugging
title.setContentHuggingPriority(UILayoutPriority(rawValue: 750), for: .horizontal)
// Resistance
title.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 750), for: .horizontal)
icon2.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 250), for: .horizontal)
title.textAlignment = .left
title.numberOfLines = 0
// Highlight stackView and set colors
stackView.addBackground(color: .green)
title.textColor = .label
icon2.backgroundColor = .cyan
// Add title and detail
stackView.addArrangedSubview(title)
stackView.addArrangedSubview(icon2)
icon2.contentMode = .center
// Add to subview
self.contentView.addSubview(stackView)
// Get layoutMarginsGuide
let layoutMarginsGuide = contentView.layoutMarginsGuide
// Set constraints
NSLayoutConstraint.activate([
// Constrain all 4 sides of the stack view to the content view's layoutMarginsGuide
stackView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: 0.0),
stackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor, constant: 0.0),
stackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor, constant: 0.0),
stackView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor, constant: 0.0),
])
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
// MARK: - AddBackground
extension UIStackView {
func addBackground(color: UIColor) {
let subView = UIView(frame: bounds)
subView.backgroundColor = color
subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
insertSubview(subView, at: 0)
}
}
解决方案
为了实现这一点,我们需要将约束更改为
contentView.
并将leadingAnchor.constraint
常量设置为16.0
。NSLayoutConstraint.activate([ stackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0.0), stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16), stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0.0), stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0.0), ])
更改
icon2.contentMode = .center
为icon2.contentMode = .scaleAspectFit
覆盖整个单元格的 StackView:
NSLayoutConstraint.activate([ stackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0.0), stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 0), stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0.0), stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0.0), ])
要更改单元格高度,我们可以简单地将高度约束添加到单元格内的任何对象:
title.addConstraint(NSLayoutConstraint(item: title, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 100))