gpt4 book ai didi

swift - UITableView 自定义单元格高度无法正确管理 swift 中的动态约束

转载 作者:行者123 更新时间:2023-11-30 10:27:03 25 4
gpt4 key购买 nike

I am having table view and took the custom cell from xib, I have lots of things to expand in the cell when there is media or bigger text, I have managed the height programmatically in the delegate method and constraint in the cell as well But sometimes when I open the app and load the data the cell gets overlapped but when I scroll up-down then it looks fine. What can I do to get that updated immediately after reloading when I get data from API?

enter image description here

我认为代码没有问题,因为它在再次刷新或滚动 TableView 后可以工作。高度委托(delegate)方法如下:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

let newsDict = self.tableDataNewsArray[indexPath.section]
let newsDataArray = newsDict["news"] as! [NewsBriefModel]
let newsObject = newsDataArray[indexPath.item]

if (self.moreExpandableArray.firstIndex(of: newsObject.newsbrief_id) != nil) {
return 62 + 58 + 4 + 62 //(62:// label minimum height )(46: other than label caponents in cell :: 4: spacing
// 62: more/less button view height)

}else if (self.lessExpandableArray.firstIndex(of: newsObject.newsbrief_id) != nil) {

var baseMoreHeight : CGFloat = newsObject.labelHeightForPostText + 58 + 4 + 62 //(46: other than label caponents in cell :: 4: spacing
// 62: more/less button view height)

if newsObject.numberOfImagesInPost > 0 {
baseMoreHeight = baseMoreHeight + 110
}
if newsObject.numberOfDocumentInPost > 0 {
baseMoreHeight = baseMoreHeight + CGFloat((newsObject.numberOfDocumentInPost * 45))
}
if newsObject.numberOfVideosInPost > 0 {
baseMoreHeight = baseMoreHeight + CGFloat((newsObject.numberOfVideosInPost * 100))
}

return baseMoreHeight
}

}

我在 cellForRow 中调用来更改 UI 的 Cell 方法:

 // MARK: CELL METHODS

func showNormalView() {

self.postTitleLabel.numberOfLines = 3
self.postTitleTextView.textContainer.maximumNumberOfLines = 3
self.postTitleTextView.textContainer.lineBreakMode = .byTruncatingTail

self.mediaViewHeight.constant = 0
self.documentTableViewHeight.constant = 0
self.videoTableViewHeight.constant = 0
self.multiMediaView.isHidden = true
self.loadImages(urlString: [])
self.updateConstraintsIfNeeded()
self.setNeedsLayout()
self.layoutIfNeeded()
}

func showMoreView() {

self.postTitleLabel.numberOfLines = 3
self.postTitleTextView.textContainer.maximumNumberOfLines = 3
self.postTitleTextView.textContainer.lineBreakMode = .byTruncatingTail

self.mediaViewHeight.constant = 50
self.imageGridViewHeight.constant = 0
self.documentTableViewHeight.constant = 0
self.videoTableViewHeight.constant = 0
self.loadImages(urlString: [])
self.multiMediaView.isHidden = false
self.updateConstraintsIfNeeded()
self.setNeedsLayout()
self.layoutIfNeeded()
}

最佳答案

我建议使用 UITableView.automaticDimension 而不是手动计算高度,并使用委托(delegate)模式来更新单元格的高度。

这是我通过这种方法得到的结果:

和代码示例:

import UIKit

struct Content {
let author: String
let date: String
let views: UInt
let recs: UInt
let content: String
}

let longText = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
"""

protocol MyCellDelegate: AnyObject {
func contentDidChange(cell: UITableViewCell)
}

final class MyCell: UITableViewCell {
static let reuseIdentifier = "MyCell"

weak var delegate: MyCellDelegate?

private var viewsCountLabel: UILabel!
private var recsLabel: UILabel!
private var authorLabel: UILabel!
private var dateLabel: UILabel!
private var contentLabel: UILabel!
private var toggleHeightButton: UIButton!

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupSubviews()
}

required init?(coder: NSCoder) {
fatalError("not implemented")
}

override func prepareForReuse() {
super.prepareForReuse()
viewsCountLabel.text = nil
recsLabel.text = nil
authorLabel.text = nil
dateLabel.text = nil
contentLabel.text = nil
contentLabel.numberOfLines = 2
}

public func setContent(_ content: Content) {
viewsCountLabel.text = "Views: \(content.views)"
recsLabel.text = "Recs: \(content.recs)"
authorLabel.text = content.author
dateLabel.text = content.date
contentLabel.text = content.content
}

private func setupSubviews() {
let leftStackView = createLeftStack()
let rightStackView = createRightStack()

let stackView = UIStackView(arrangedSubviews: [leftStackView, rightStackView])
stackView.axis = .horizontal
stackView.spacing = 5
stackView.alignment = .top

contentView.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10),
stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10),
stackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 3),
stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -3)
])
}

private func createLeftStack() -> UIStackView {
let iconView = createIconView()
viewsCountLabel = createLabel()
recsLabel = createLabel()
let stackView = UIStackView(arrangedSubviews: [iconView, viewsCountLabel, recsLabel])
stackView.axis = .vertical
stackView.setCustomSpacing(4, after: iconView)
stackView.alignment = .leading
return stackView
}

private func createRightStack() -> UIStackView {
authorLabel = createLabel()
dateLabel = createLabel()
contentLabel = UILabel()
contentLabel.font = UIFont.systemFont(ofSize: 13, weight: .bold)
contentLabel.contentMode = .topLeft

toggleHeightButton = UIButton(type: .system)
toggleHeightButton.setTitle("Toggle", for: .normal)
toggleHeightButton.addTarget(self, action: #selector(expandDidTap), for: .touchUpInside)
toggleHeightButton.heightAnchor.constraint(equalToConstant: 30).isActive = true

let stackView = UIStackView(arrangedSubviews: [authorLabel, dateLabel, contentLabel, toggleHeightButton])
stackView.axis = .vertical
stackView.alignment = .leading
return stackView
}

private func createIconView() -> UIView {
let iconView = UIView()
iconView.backgroundColor = .blue
iconView.layer.cornerRadius = 4
iconView.layer.masksToBounds = true
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 8)
label.numberOfLines = 2
label.text = "Upload Icon"
label.textAlignment = .center
label.textColor = .white
iconView.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
iconView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
label.leadingAnchor.constraint(equalTo: iconView.leadingAnchor, constant: 3),
label.trailingAnchor.constraint(equalTo: iconView.trailingAnchor, constant: -3),
label.topAnchor.constraint(equalTo: iconView.topAnchor, constant: 3),
label.bottomAnchor.constraint(equalTo: iconView.bottomAnchor, constant: -3),
iconView.heightAnchor.constraint(equalToConstant: 40),
iconView.widthAnchor.constraint(equalToConstant: 40)
])
return iconView
}

private func createLabel() -> UILabel {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 8, weight: .light)
label.numberOfLines = 1
return label
}

@objc func expandDidTap() {
let isExpand = contentLabel.numberOfLines != 0
if isExpand {
contentLabel.numberOfLines = 0
} else {
contentLabel.numberOfLines = 2
}
delegate?.contentDidChange(cell: self)
}
}

final class MyViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
private var tableView: UITableView {
view as! UITableView
}

private var data: [Content] = [] {
didSet {
tableView.reloadData()
}
}

override func loadView() {
let tableView = UITableView()
tableView.delegate = self
tableView.dataSource = self
tableView.register(MyCell.self, forCellReuseIdentifier: MyCell.reuseIdentifier)
view = tableView
}

override func viewDidLoad() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.data = [
Content(author: "Author1", date: "15:07", views: 2, recs: 1, content: longText),
Content(author: "Author2", date: "15:07", views: 2, recs: 1, content: longText),
Content(author: "Author3", date: "15:07", views: 2, recs: 1, content: longText),
Content(author: "Author1", date: "15:07", views: 2, recs: 1, content: longText)
]
}
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
data.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: MyCell.reuseIdentifier, for: indexPath) as! MyCell
cell.delegate = self
let content = data[indexPath.row]
cell.setContent(content)
return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}

extension MyViewController: MyCellDelegate {
func contentDidChange(cell: UITableViewCell) {
UIView.animate(withDuration: 0.2) {
self.tableView.beginUpdates()
self.tableView.endUpdates()
}
}
}

关于swift - UITableView 自定义单元格高度无法正确管理 swift 中的动态约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59965093/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com