Ios UITableViewCell未按预期显示约束
我试图以编程方式创建一个tableview单元格,但在按预期布局时遇到了一些问题。我认为这取决于我调用事物的顺序,但我无法按预期显示内容(我在uiview上尝试了插入和其他约束,它似乎工作正常) 我在VC中注册tableview单元格,我还在cellforrow中退出可重用单元格的队列,在这里我传递activity对象以更新单元格UI。该单元格的高度由heightforrow回调设置为300 活动单元代码Ios UITableViewCell未按预期显示约束,ios,swift,uitableview,uikit,Ios,Swift,Uitableview,Uikit,我试图以编程方式创建一个tableview单元格,但在按预期布局时遇到了一些问题。我认为这取决于我调用事物的顺序,但我无法按预期显示内容(我在uiview上尝试了插入和其他约束,它似乎工作正常) 我在VC中注册tableview单元格,我还在cellforrow中退出可重用单元格的队列,在这里我传递activity对象以更新单元格UI。该单元格的高度由heightforrow回调设置为300 活动单元代码 class ActivityCell: UITableViewCell {
class ActivityCell: UITableViewCell {
private var activityCard = UIView()
private var verticalStack = UIStackView()
private var nameStack = UIStackView() // top horizontal stack
private let profileImage = UIImageView()
private let profileNameLbl = UILabel()
private let dateLbl = UILabel()
private let raceVerticalStack = UIStackView() //middle
private let topRaceStack = UIStackView()
private let bottomRaceStack = UIStackView()
private let raceNameStack = UIStackView()
private let raceNameLbl = UILabel()
private let distanceStack = UIStackView()
private let distanceLbl = UILabel()
private let distanceValueLbl = UILabel()
private let timeStack = UIStackView()
private let timeLbl = UILabel()
private let timeValueLbl = UILabel()
private let paceStack = UIStackView()
private let paceLbl = UILabel()
private let paceValueLbl = UILabel()
private let positionStack = UIStackView()
private let positionLbl = UILabel()
private let positionValueLbl = UILabel()
private let pointsStack = UIStackView()
private let pointsLbl = UILabel()
private let pointsValueLbl = UILabel()
private let bottomStack = UIStackView() //bottom
private let clapStack = UIStackView()
private let clapIcon = UIImageView()
private let clapCountLbl = UILabel()
private let clapCommentStack = UIStackView()
private let commentStack = UIStackView()
private let commentIcon = UIImageView()
private let commentCountLbl = UILabel()
private let clapButton = UIButton() // interaction buttons
private let commentButton = UIButton()
private let gradientStart = UIColor(red: 24/255, green: 44/255, blue: 86/255, alpha: 1.0)
private let gradientEnd = UIColor(red: 234/255, green: 82/255, blue: 119/255, alpha: 1.0)
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
layer.masksToBounds = true
self.contentView.layer.masksToBounds = true
activityCard.frame = self.frame.inset(by: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10))
verticalStack.frame = activityCard.frame
setupHierarchy()
setConstraints()
configureView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func configureView() {
labelSetup()
buttonSetup()
stackViewSetup()
imageSetup()
stackViewSetup()
setShadow()
}
func updateCell(with activity: RaceActivity) {
profileNameLbl.text = activity.runnerName
profileImage.image = activity.profileImage
raceNameLbl.text = activity.raceName
distanceValueLbl.text = activity.distance
timeValueLbl.text = activity.time
paceValueLbl.text = activity.pace
positionValueLbl.text = activity.position
pointsValueLbl.text = activity.points
}
private func labelSetup() {
profileNameLbl.font = .Graphik()
raceNameLbl.font = .Graphik(.medium, size: 22)
dateLbl.font = .Graphik(.light, size: 17)
distanceLbl.font = .Graphik()
timeLbl.font = .Graphik()
paceLbl.font = .Graphik()
positionLbl.font = .Graphik()
pointsLbl.font = .Graphik()
clapCountLbl.font = .Graphik()
commentCountLbl.font = .Graphik()
paceLbl.font = .Graphik()
distanceValueLbl.font = .Graphik(.medium)
timeValueLbl.font = .Graphik(.medium)
paceValueLbl.font = .Graphik(.medium)
positionValueLbl.font = .Graphik(.medium)
timeLbl.textAlignment = .left
paceLbl.textAlignment = .center
paceValueLbl.textAlignment = .center
pointsLbl.textAlignment = .left
pointsValueLbl.textAlignment = .left
dateLbl.textAlignment = .right
clapCountLbl.text = "33"
commentCountLbl.text = "12"
positionLbl.text = "Position"
pointsLbl.text = "Points"
distanceLbl.text = "Distance"
timeLbl.text = "Time"
paceLbl.text = "Pace"
dateLbl.text = "Friday"
}
private func stackViewSetup() {
nameStack.distribution = .fillProportionally
topRaceStack.distribution = .fillEqually
bottomRaceStack.distribution = .fillEqually
clapCommentStack.distribution = .fillEqually
bottomStack.distribution = .fillEqually
raceNameStack.axis = .horizontal
nameStack.axis = .horizontal
verticalStack.axis = .vertical
raceVerticalStack.axis = .vertical
bottomStack.axis = .horizontal
topRaceStack.axis = .horizontal
bottomRaceStack.axis = .horizontal
distanceStack.axis = .vertical
timeStack.axis = .vertical
paceStack.axis = .vertical
positionStack.axis = .vertical
pointsStack.axis = .vertical
nameStack.spacing = 10
verticalStack.spacing = 5
raceVerticalStack.spacing = 10
bottomStack.spacing = 10
nameStack.alignment = .center
distanceStack.alignment = .center
timeStack.alignment = .center
paceStack.alignment = .center
pointsStack.alignment = .center
positionStack.alignment = .center
clapCommentStack.alignment = .center
bottomStack.alignment = .center
raceVerticalStack.spacing = 5
topRaceStack.spacing = 2
clapCommentStack.spacing = 3
clapStack.spacing = 4
commentStack.spacing = 4
}
private func buttonSetup() {
clapButton.setTitle("Clap", for: .normal)
clapButton.setTitleColor(.darkGray, for: .normal)
clapButton.titleLabel?.font = .Graphik(.regular, size: 14)
clapButton.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
clapButton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 30)
clapButton.setImage(UIImage(named: "clap"), for: .normal)
commentButton.setTitle("Comment", for: .normal)
commentButton.setTitleColor(.darkGray, for: .normal)
commentButton.titleLabel?.font = .Graphik(.regular, size: 14)
commentButton.titleEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
commentButton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 10)
commentButton.setImage(UIImage(named: "comment"), for: .normal)
}
private func imageSetup() {
profileImage.layer.cornerRadius = 15
profileImage.backgroundColor = .lightGray
clapIcon.image = UIImage(named: "clapGrey")
clapIcon.contentMode = .scaleAspectFit
commentIcon.image = UIImage(named: "commentGrey")
commentIcon.contentMode = .scaleAspectFit
}
private func setShadow() {
let gradient = CAGradientLayer()
gradient.frame = CGRect(origin: CGPoint(x: 10, y: 5), size: frame.size)
gradient.colors = [gradientStart.cgColor, gradientEnd.cgColor]
let border = CAShapeLayer()
border.lineWidth = 2
border.path = UIBezierPath(roundedRect: frame.inset(by: UIEdgeInsets(top: 10, left: 2, bottom: 10, right: 22)), cornerRadius: 12).cgPath
border.strokeColor = UIColor.black.cgColor
border.fillColor = UIColor.clear.cgColor
gradient.mask = border
removeExistingGradient(from: self)
self.layer.addSublayer(gradient)
}
private func setConstraints() {
let constraints = [
nameStack.heightAnchor.constraint(equalToConstant: 50),
raceNameStack.heightAnchor.constraint(equalToConstant: 30),
topRaceStack.heightAnchor.constraint(equalToConstant: 60),
bottomRaceStack.heightAnchor.constraint(equalToConstant: 60),
profileImage.heightAnchor.constraint(equalToConstant: 30),
profileImage.widthAnchor.constraint(equalToConstant: 30),
commentButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 90),
clapButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 90),
clapIcon.widthAnchor.constraint(equalToConstant: 15),
commentIcon.widthAnchor.constraint(equalToConstant: 15),
]
NSLayoutConstraint.activate(constraints)
setupMargins()
}
private func setupMargins() {
nameStack.layoutMargins = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 25)
raceNameStack.layoutMargins = UIEdgeInsets(top:0, left: 20, bottom: 0, right: 0)
raceVerticalStack.layoutMargins = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 35)
bottomStack.layoutMargins = UIEdgeInsets(top: 0, left: 20, bottom: 10, right: 30)
nameStack.isLayoutMarginsRelativeArrangement = true
topRaceStack.isLayoutMarginsRelativeArrangement = true
bottomRaceStack.isLayoutMarginsRelativeArrangement = true
raceNameStack.isLayoutMarginsRelativeArrangement = true
bottomStack.isLayoutMarginsRelativeArrangement = true
addLines()
}
private func addLines() {
guard bottomStack.frame.height > 0 else { return }
let horizontalStart = CGPoint(x: bottomStack.frame.minX, y: bottomStack.frame.minY)
let bottomLine = UIView(frame: CGRect(x: horizontalStart.x + 20, y: horizontalStart.y + 12, width: bottomStack.frame.width - 40, height: 1.0))
bottomLine.tag = 99
bottomLine.layer.borderWidth = 0.8
bottomLine.layer.borderColor = UIColor.lightGray.cgColor
let clapStackLine = UIView(frame: CGRect(x: clapCommentStack.frame.maxX, y: horizontalStart.y + 22, width: 1.0, height: clapCommentStack.frame.maxY - clapCommentStack.frame.minY))
clapStackLine.layer.borderWidth = 0.8
clapStackLine.layer.borderColor = UIColor.lightGray.cgColor
let commentLine = UIView(frame: CGRect(x: clapButton.frame.maxX, y: horizontalStart.y + 22, width: 1.0, height: clapCommentStack.frame.maxY - clapCommentStack.frame.minY))
commentLine.layer.borderWidth = 0.8
commentLine.layer.borderColor = UIColor.lightGray.cgColor
let topLine = UIView(frame: CGRect(x: horizontalStart.x + 20, y: nameStack.frame.maxY + 5, width: bottomStack.frame.width - 40, height: 1.0))
topLine.layer.borderWidth = 0.8
topLine.layer.borderColor = UIColor.lightGray.cgColor
self.activityCard.addSubview(bottomLine)
self.activityCard.addSubview(clapStackLine)
self.activityCard.addSubview(commentLine)
self.activityCard.addSubview(topLine)
}
private func setupHierarchy() {
nameStack.addArrangedSubview(profileImage)
nameStack.addArrangedSubview(profileNameLbl)
nameStack.addArrangedSubview(dateLbl)
raceVerticalStack.addArrangedSubview(raceNameStack)
raceVerticalStack.addArrangedSubview(topRaceStack)
raceVerticalStack.addArrangedSubview(bottomRaceStack)
raceNameStack.addArrangedSubview(raceNameLbl)
topRaceStack.addArrangedSubview(distanceStack)
topRaceStack.addArrangedSubview(timeStack)
topRaceStack.addArrangedSubview(paceStack)
bottomRaceStack.addArrangedSubview(positionStack)
bottomRaceStack.addArrangedSubview(pointsStack)
bottomRaceStack.addArrangedSubview(UIView())
distanceStack.addArrangedSubview(distanceLbl)
distanceStack.addArrangedSubview(distanceValueLbl)
timeStack.addArrangedSubview(timeLbl)
timeStack.addArrangedSubview(timeValueLbl)
paceStack.addArrangedSubview(paceLbl)
paceStack.addArrangedSubview(paceValueLbl)
positionStack.addArrangedSubview(positionLbl)
positionStack.addArrangedSubview(positionValueLbl)
pointsStack.addArrangedSubview(pointsLbl)
pointsStack.addArrangedSubview(pointsValueLbl)
clapStack.addArrangedSubview(clapIcon)
clapStack.addArrangedSubview(clapCountLbl)
commentStack.addArrangedSubview(commentIcon)
commentStack.addArrangedSubview(commentCountLbl)
clapCommentStack.addArrangedSubview(clapStack)
clapCommentStack.addArrangedSubview(commentStack)
mainStackHierarchy()
}
private func mainStackHierarchy() {
bottomStack.addArrangedSubview(clapCommentStack)
bottomStack.addArrangedSubview(clapButton)
bottomStack.addArrangedSubview(commentButton)
verticalStack.addArrangedSubview(nameStack)
verticalStack.addArrangedSubview(raceNameStack)
verticalStack.addArrangedSubview(raceVerticalStack)
verticalStack.addArrangedSubview(bottomStack)
activityCard.addSubview(verticalStack)
self.contentView.addSubview(activityCard)
}
}
当前输出的屏幕截图:
预期输出的屏幕截图:
感谢您的帮助:D您遇到了问题,因为您使用了大量显式框架,而不是利用自动布局 首先,如果您将
init()
func更改为此并运行应用程序:
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
layer.masksToBounds = true
self.contentView.layer.masksToBounds = true
// no need to set frames
//activityCard.frame = self.frame.inset(by: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10))
//verticalStack.frame = activityCard.frame
setupHierarchy()
setConstraints()
configureView()
activityCard.translatesAutoresizingMaskIntoConstraints = false
verticalStack.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
activityCard.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10.0),
activityCard.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10.0),
activityCard.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10.0),
activityCard.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10.0),
verticalStack.topAnchor.constraint(equalTo: activityCard.topAnchor, constant: 6.0),
verticalStack.leadingAnchor.constraint(equalTo: activityCard.leadingAnchor, constant: 6.0),
verticalStack.trailingAnchor.constraint(equalTo: activityCard.trailingAnchor, constant: -6.0),
verticalStack.bottomAnchor.constraint(equalTo: activityCard.bottomAnchor, constant: -6.0),
])
}
你会发现你离你想要的更近了
接下来,改变:
private var activityCard = UIView()
致:
并使用该类:
class ActivityCardView: UIView {
private let gradientStart = UIColor(red: 24/255, green: 44/255, blue: 86/255, alpha: 1.0)
private let gradientEnd = UIColor(red: 234/255, green: 82/255, blue: 119/255, alpha: 1.0)
private let gradLayer = CAGradientLayer()
override init(frame: CGRect) {
super.init(frame: frame)
layer.addSublayer(gradLayer)
gradLayer.colors = [gradientStart.cgColor, gradientEnd.cgColor]
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
gradLayer.frame = bounds
let border = CAShapeLayer()
border.lineWidth = 2
border.path = UIBezierPath(roundedRect: bounds.inset(by: UIEdgeInsets(top: 10, left: 2, bottom: 10, right: 2)), cornerRadius: 12).cgPath
border.strokeColor = UIColor.black.cgColor
border.fillColor = UIColor.clear.cgColor
gradLayer.mask = border
}
}
然后,从cell类中删除您的private func setShadow()
。此ActivityCardView
类将自动处理渐变边框
对于“分隔符”行,您最好将它们添加为垂直堆栈的排列子视图,而不是尝试使用绝对坐标定位它们:
private func mainStackHierarchy() {
bottomStack.addArrangedSubview(clapCommentStack)
bottomStack.addArrangedSubview(clapButton)
bottomStack.addArrangedSubview(commentButton)
verticalStack.addArrangedSubview(nameStack)
var hLineView = UIView()
hLineView.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
hLineView.backgroundColor = .lightGray
verticalStack.addArrangedSubview(hLineView)
verticalStack.addArrangedSubview(raceNameStack)
verticalStack.addArrangedSubview(raceVerticalStack)
hLineView = UIView()
hLineView.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
hLineView.backgroundColor = .lightGray
verticalStack.addArrangedSubview(hLineView)
verticalStack.addArrangedSubview(bottomStack)
activityCard.addSubview(verticalStack)
self.contentView.addSubview(activityCard)
}
此时,您的输出应该如下所示:
种族名称上的下划线可能最好通过使用带有下划线样式的属性文本来处理
我想您可能想对间距进行一些调整,但这应该不会有任何问题。太棒了!非常感谢,我不敢相信我忽略了为活动卡创建一个新类。我想我是在考虑故事板设计而不是利用编程方式创建UI元素的优点
private func mainStackHierarchy() {
bottomStack.addArrangedSubview(clapCommentStack)
bottomStack.addArrangedSubview(clapButton)
bottomStack.addArrangedSubview(commentButton)
verticalStack.addArrangedSubview(nameStack)
var hLineView = UIView()
hLineView.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
hLineView.backgroundColor = .lightGray
verticalStack.addArrangedSubview(hLineView)
verticalStack.addArrangedSubview(raceNameStack)
verticalStack.addArrangedSubview(raceVerticalStack)
hLineView = UIView()
hLineView.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
hLineView.backgroundColor = .lightGray
verticalStack.addArrangedSubview(hLineView)
verticalStack.addArrangedSubview(bottomStack)
activityCard.addSubview(verticalStack)
self.contentView.addSubview(activityCard)
}