如何在UITableViewCell内部更新UITableView的高度约束
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在UITableViewCell内部更新UITableView的高度约束相关的知识,希望对你有一定的参考价值。
我有一个UITableView,它显示用户发表的评论。这些单元格内部可能包含对评论的回复,我使用另一个UITableView显示了该评论。我当前正在做的是在设置时将此内部UITableView的高度(回复评论)设置为500,然后在layoutSubviews中计算此内部UITableViewCells的可见答复单元格,然后根据计算结果更改此内部UITableView的高度。我目前遇到的问题是,在加载时,我的布局到处都是(参见图1),但是,uppon在外部UITableView上上下滚动了几次,才得到正确的所需的布局(图2)。请有人可以建议如何更新约束,以便在加载时获得正确的布局吗?
主UItableView
class CommentOnPostTableView: UITableView, UITableViewDataSource, UITableViewDelegate
var items: [Comment]?
var post: ResearchPost?
let cellIDB = "commentCellId"
init(frame: CGRect, style: UITableView.Style, sourceData: [Comment], postContent: ResearchPost)
super.init(frame: frame, style: style)
items = sourceData
post = postContent
self.dataSource = self
self.delegate = self
self.register(CommentTableViewCell.self, forCellReuseIdentifier: cellIDB)
required init?(coder: NSCoder)
fatalError("init(coder:) has not been implemented")
extension CommentOnPostTableView
/***Number of cells*/
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
if let dataSource = items
return dataSource.count
else
return 0
/***Create Cell*/
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
guard let dataSource = items elsereturn UITableViewCell.init()
let cell = tableView.dequeueReusableCell(withIdentifier: cellIDB, for: indexPath) as! CommentTableViewCell
cell.dataObject = dataSource[indexPath.row - 1]
return cell
主UITableViewCell:
class CommentTableViewCell: UITableViewCell
var nameLabel: UILabel =
let label = UILabel()
label.font = .boldSystemFont(ofSize: 11)
label.translatesAutoresizingMaskIntoConstraints = false
return label
()
var imgView: UIImageView =
let view = UIImageView()
view.backgroundColor = UIColor.black
view.contentMode = .scaleAspectFit
view.translatesAutoresizingMaskIntoConstraints = false
return view
()
var replyLabel: UILabel =
let label = UILabel()
label.text = "Reply"
label.textColor = UIColor.appGrayForButtonTitles
label.font = UIFont.systemFont(ofSize: 11)
label.translatesAutoresizingMaskIntoConstraints = false
return label
()
var numRepliesLabel: UILabel =
let label = UILabel()
label.font = .boldSystemFont(ofSize: 11)
label.textColor = UIColor.app0946BF
label.textAlignment = .right
label.translatesAutoresizingMaskIntoConstraints = false
return label
()
var repliesTextLabel: UILabel =
let label = UILabel()
label.text = "Replies"
label.font = .boldSystemFont(ofSize: 11)
label.textColor = UIColor.app0946BF
label.translatesAutoresizingMaskIntoConstraints = false
return label
()
var timeReplyContainer: UIView =
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
()
var timeAgoLabel: UILabel =
let label = UILabel()
label.text = "1 hr"
label.textColor = UIColor.appGrayLight
label.font = UIFont.systemFont(ofSize: 11)
label.translatesAutoresizingMaskIntoConstraints = false
return label
()
var timeTextLabel: UILabel =
let label = UILabel()
label.textColor = UIColor.appGrayLight
label.text = "ago"
label.font = UIFont.systemFont(ofSize: 11)
label.translatesAutoresizingMaskIntoConstraints = false
return label
()
var repliesContainer: UIView =
let view = UIView()
view.backgroundColor = UIColor.yellow
view.translatesAutoresizingMaskIntoConstraints = false
return view
()
var cellIndexPath: IndexPath?
var commentLabel: LabelWithPadding!
var repliesTableView: RepliesToCommentsTableView!
var replyToCommentItems = [Comment]()
let repliesID = "repliesToCommentsID"
var numberOfRepliesToComment: Int = 0
fileprivate var oldConstraints = [NSLayoutConstraint]()
fileprivate var oldReplyTableHeightConstraints = [NSLayoutConstraint]()
fileprivate var totalCellHeight: CGFloat?
/** init is called before dataObject.didSet*/
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?)
super.init(style: style, reuseIdentifier: reuseIdentifier)
print("CommentTableViewCell.INIT")
self.selectionStyle = .none
setupViews()
var dataObject: Comment?
didSet
if let data = dataObject
guard
let image = data.imageOfCommentor,
let name = data.name,
let comment = data.comment,
let replies = data.repliesToComment elsereturn
print("dataObject.didSet for :\(name)")
repliesTableView.sourceData = replies
repliesTableView.reloadData()
numberOfRepliesToComment = replies.count
numRepliesLabel.text = "\(replies.count)"
imgView.image = image
nameLabel.text = name
commentLabel.label.text = comment
override func updateConstraints()
print("updateConstraints for : \(nameLabel.text!)")
super.updateConstraints()
override func layoutSubviews()
super.layoutSubviews()
print("layoutSubviews for \(nameLabel.text!)")
let repliesVisible = repliesTableView.visibleCells
if repliesVisible.count > 0
UIView.animate(withDuration: 0)
//self.layoutIfNeeded()
self.totalCellHeight = 0.0
for reply in repliesVisible
self.totalCellHeight! += reply.frame.height
NSLayoutConstraint.deactivate(self.oldReplyTableHeightConstraints)
let newHeightConstraint = self.repliesTableView.heightAnchor.constraint(equalToConstant: self.totalCellHeight!)
let newHeightArray: [NSLayoutConstraint] = [newHeightConstraint]
self.oldReplyTableHeightConstraints = newHeightArray
NSLayoutConstraint.activate(self.oldReplyTableHeightConstraints)
self.layoutIfNeeded()
else
// Do not show repliesTableView
NSLayoutConstraint.deactivate(self.oldReplyTableHeightConstraints)
let newHeightConstraint = self.repliesTableView.heightAnchor.constraint(equalToConstant: 0.0)
let newHeightArray: [NSLayoutConstraint] = [newHeightConstraint]
self.oldReplyTableHeightConstraints = newHeightArray
NSLayoutConstraint.activate(self.oldReplyTableHeightConstraints)
self.layoutIfNeeded()
self.commentLabel.layoutIfNeeded()
required init?(coder: NSCoder)
fatalError("init(coder:) has not been implemented")
let borderSpace: CGFloat = 10
let viewSpace: CGFloat = 5
private func setupViews()
let c = contentView.safeAreaLayoutGuide
/**Create commentLabel*/
let padding = UIEdgeInsets.init(top: 3, left: 5, bottom: 3, right: 5)
commentLabel = LabelWithPadding.init(frame: .zero, with: padding)
commentLabel.translatesAutoresizingMaskIntoConstraints = false
/**Create reply to comments tableView*/
repliesTableView = RepliesToCommentsTableView.init(frame: .zero, style: .plain, sourceData: replyToCommentItems, cellid: repliesID)
repliesTableView.translatesAutoresizingMaskIntoConstraints = false
repliesTableView.isScrollEnabled = false
repliesTableView.backgroundColor = UIColor.green
timeReplyContainer.addSubview(timeAgoLabel)
timeReplyContainer.addSubview(timeTextLabel)
timeReplyContainer.addSubview(replyLabel)
timeReplyContainer.addSubview(numRepliesLabel)
timeReplyContainer.addSubview(repliesTextLabel)
contentView.addSubview(imgView)
contentView.addSubview(nameLabel)
contentView.addSubview(commentLabel)
contentView.addSubview(timeReplyContainer)
contentView.addSubview(repliesTableView)
commentLabel.label.font = UIFont.systemFont(ofSize: 12)
commentLabel.label.numberOfLines = 0
commentLabel.label.lineBreakMode = .byWordWrapping
commentLabel.layer.cornerRadius = 7
commentLabel.layer.masksToBounds = true
commentLabel.backgroundColor = UIColor.appGrayExtraLightGray
/**Layout constraints*/
NSLayoutConstraint.deactivate(oldConstraints)
NSLayoutConstraint.deactivate(oldReplyTableHeightConstraints)
let newConstraints = [
imgView.topAnchor.constraint(equalTo: c.topAnchor, constant: borderSpace),
imgView.leadingAnchor.constraint(equalTo: c.leadingAnchor, constant: borderSpace),
imgView.widthAnchor.constraint(equalTo: c.widthAnchor, multiplier: 0.08),
imgView.heightAnchor.constraint(equalTo: c.widthAnchor, multiplier: 0.08),
nameLabel.topAnchor.constraint(equalTo: c.topAnchor, constant: borderSpace),
nameLabel.leadingAnchor.constraint(equalTo: imgView.trailingAnchor, constant: 10),
nameLabel.trailingAnchor.constraint(equalTo: c.trailingAnchor, constant: -borderSpace),
commentLabel.topAnchor.constraint(equalTo: nameLabel.bottomAnchor, constant: viewSpace),
commentLabel.widthAnchor.constraint(equalTo: nameLabel.widthAnchor),
commentLabel.trailingAnchor.constraint(equalTo: c.trailingAnchor, constant: -borderSpace),
timeReplyContainer.topAnchor.constraint(equalTo: commentLabel.bottomAnchor, constant: borderSpace),
timeReplyContainer.heightAnchor.constraint(equalToConstant: 30),
timeReplyContainer.widthAnchor.constraint(equalTo: nameLabel.widthAnchor),
timeReplyContainer.trailingAnchor.constraint(equalTo: c.trailingAnchor, constant: -borderSpace),
timeReplyContainer.bottomAnchor.constraint(equalTo: repliesTableView.topAnchor, constant: -10),
timeAgoLabel.leadingAnchor.constraint(equalTo: timeReplyContainer.leadingAnchor, constant: 5),
timeAgoLabel.topAnchor.constraint(equalTo: timeReplyContainer.topAnchor),
timeAgoLabel.trailingAnchor.constraint(equalTo: timeTextLabel.leadingAnchor, constant: -5),
timeAgoLabel.topAnchor.constraint(equalTo: timeTextLabel.topAnchor),
timeTextLabel.topAnchor.constraint(equalTo: timeReplyContainer.topAnchor),
timeTextLabel.trailingAnchor.constraint(equalTo: replyLabel.leadingAnchor, constant: -10),
replyLabel.topAnchor.constraint(equalTo: timeReplyContainer.topAnchor),
numRepliesLabel.topAnchor.constraint(equalTo: timeReplyContainer.topAnchor),
numRepliesLabel.trailingAnchor.constraint(equalTo: repliesTextLabel.leadingAnchor, constant: -5),
repliesTextLabel.topAnchor.constraint(equalTo: timeReplyContainer.topAnchor),
repliesTextLabel.trailingAnchor.constraint(equalTo: timeReplyContainer.trailingAnchor),
repliesTableView.widthAnchor.constraint(equalTo: nameLabel.widthAnchor),
repliesTableView.trailingAnchor.constraint(equalTo: c.trailingAnchor, constant: -borderSpace),
repliesTableView.bottomAnchor.constraint(equalTo: c.bottomAnchor, constant: -borderSpace)
]
NSLayoutConstraint.activate([repliesTableView.heightAnchor.constraint(equalToConstant: 500)])
NSLayoutConstraint.activate(newConstraints)
oldConstraints = newConstraints
oldReplyTableHeightConstraints = [repliesTableView.heightAnchor.constraint(equalToConstant: 500)]
图1:
图2:
在外部表视图的cellForRowAt
功能期间设置内部表视图的高度。另外,我将覆盖updateConstraints
,在其中设置约束,然后在init / setup函数中为每个单元格调用setNeedsUpdateConstraints
以上是关于如何在UITableViewCell内部更新UITableView的高度约束的主要内容,如果未能解决你的问题,请参考以下文章
仅为 UITableViewCell 的一部分调用 didSelectRowAtIndexPath
滚动后 UITableViewCell 标签发生变化[重复]
保存 UITableviewcell accessoryView 的状态
dequeueReusableCellWithIdentifier、自定义 UITableViewCell 的问题