如何更改 tableview willDisplay 函数中的布局和属性设置?
Posted
技术标签:
【中文标题】如何更改 tableview willDisplay 函数中的布局和属性设置?【英文标题】:How to change layout and property setting in tableview willDisplay function? 【发布时间】:2018-12-27 03:05:36 【问题描述】:我有一个问题。 我有一个 UITableView 和一个自定义 UITableViewCell。 首先,我将检查自定义 UITableViewCell 中的 UILabel 是否被截断。 如果 UILabel 被截断,我将显示 UIButton“显示更多”,并将 UILabel numberOfLines 设置为 2。 当我单击 UIButton“显示更多”时,我将 UILabel numberOfLines 设置为 0,并且 UIButton 标题更改为“关闭”。 UITableViewCell 的高度是根据 UILabel 内容展开的。 如果 UILabel 没有被截断,我不会显示 UIButton 并将 UILabel numberOfLines 设置为 0。 UITableViewCell 的高度也是根据 UILabel 内容展开的。 如何实现这种情况? 谢谢。
如何去除下图中的红色方块?
class ViewController: UIViewController
let itemCount: Int = 10
let tableView = UITableView()
let cellWithButton = "cellWithButton"
var isExpand: Bool = false
var expandingStateArray: [Bool] = []
let textArray: [String] = ["If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm", "If you read and listen to two", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day", "If you read and listen to two articles every day, your reading and listening skills", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm"]
override func viewDidLoad()
super.viewDidLoad()
for _ in 0...itemCount-1
let bool = false
expandingStateArray.append(bool)
tableView.delegate = self
tableView.dataSource = self
tableView.allowsSelection = false
tableView.separatorInset = .zero
tableView.estimatedRowHeight = 44
tableView.rowHeight = UITableViewAutomaticDimension
tableView.register(WithButtonTableViewCell.self, forCellReuseIdentifier: cellWithButton)
self.view.addSubview(tableView)
tableView.snp.makeConstraints (make) in
make.top.left.right.bottom.equalToSuperview()
@objc func btnPressed(sender: UIButton)
let indexPath = IndexPath(row: sender.tag, section: 0)
if self.isExpand == false
self.isExpand = true
expandingStateArray[sender.tag] = true
else
self.isExpand = false
expandingStateArray[sender.tag] = false
tableView.beginUpdates()
tableView.reloadRows(at: [indexPath], with: .none)
tableView.endUpdates()
extension ViewController: UITableViewDelegate, UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return itemCount
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: cellWithButton, for: indexPath) as! WithButtonTableViewCell
cell.titleLabel.text = textArray[indexPath.row]
cell.expandButton.addTarget(self, action: #selector(btnPressed), for: .touchUpInside)
cell.expandButton.tag = indexPath.row
if expandingStateArray[indexPath.row]
cell.titleLabel.numberOfLines = 0
cell.expandButton.setTitle("Close.", for: .normal)
else
cell.titleLabel.numberOfLines = 2
cell.expandButton.setTitle("Show More.", for: .normal)
return cell
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
if let btnCell = cell as? WithButtonTableViewCell
let labelIsTruncated: Bool = btnCell.titleLabel.isTruncated()
btnCell.expandButton.isHidden = !labelIsTruncated
extension UILabel
func countLabelLines() -> Int
self.layoutIfNeeded()
let myText = self.text! as NSString
let attributes = [NSAttributedStringKey.font : self.font!]
let labelSize = myText.boundingRect(with: CGSize(width: self.bounds.width, height: CGFloat.greatestFiniteMagnitude), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: attributes, context: nil)
return Int(ceil(CGFloat(labelSize.height) / self.font.lineHeight))
func isTruncated() -> Bool
if (self.countLabelLines() > self.numberOfLines)
return true
return false
import UIKit
class WithButtonTableViewCell: UITableViewCell
var cellIsExpand: Bool = false
let titleLabel: UILabel = () -> UILabel in
let ui = UILabel()
ui.textColor = UIColor.black
ui.numberOfLines = 2
return ui
()
let expandButton: UIButton = () -> UIButton in
let ui = UIButton()
ui.setTitleColor(UIColor.blue, for: .normal)
return ui
()
override func awakeFromNib()
super.awakeFromNib()
// Initialization code
override func setSelected(_ selected: Bool, animated: Bool)
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
override init(style: UITableViewCellStyle, reuseIdentifier: String?)
super.init(style: style, reuseIdentifier: reuseIdentifier)
loadUI()
loadLayout()
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
func loadUI()
self.addSubview(titleLabel)
self.addSubview(expandButton)
func loadLayout()
titleLabel.snp.makeConstraints (make) in
make.top.left.equalTo(15)
make.right.equalTo(-15)
expandButton.snp.makeConstraints (make) in
make.top.equalTo(titleLabel.snp.bottom).offset(10)
make.left.equalTo(10)
make.right.equalTo(-15)
make.bottom.equalTo(-15)
【问题讨论】:
【参考方案1】:我认为这是一个完美的工作 UIStackView
,作为设置
self.expandButton.isHidden = true
将折叠内容,否则钩住按钮的高度约束并将其设置为
btnCell.btnHCon?.constant = 0
btnCell.layoutIfNeeded()
当你想隐藏它时
var btnHCon: Constraint? = nil
expandButton.snp.makeConstraints (make) in
make.top.equalTo(titleLabel.snp.bottom).offset(10)
make.left.equalTo(10)
make.right.equalTo(-15)
make.bottom.equalTo(-15)
self.btnHCon = make.height.equalTo(40).constraint
【讨论】:
我找不到 btnCell.btnHCon?.constant = 0 ,我用的是 xcode9.4.1, snapKit 4.0.0 并得到一个错误“常量”由于“私人”保护级别而无法访问【参考方案2】:给显示更多按钮设置高度限制,当你不想显示时将其设置为0。
【讨论】:
有什么例子吗?【参考方案3】:就像第一条评论说的: 当您使用自调整单元格时,您应该更新布局。因此,您应该设置一个高度约束,让单元格的 contentView 知道它,并且当其子视图的约束发生变化时,单元格将调整大小。 我下载了你的代码并在下面修改:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: cellWithButton, for: indexPath) as! WithButtonTableViewCell
cell.titleLabel.text = textArray[indexPath.row]
cell.expandButton.addTarget(self, action: #selector(btnPressed), for: .touchUpInside)
cell.expandButton.tag = indexPath.row
if expandingStateArray[indexPath.row]
cell.titleLabel.numberOfLines = 0
cell.expandButton.setTitle("Close.", for: .normal)
else
cell.titleLabel.numberOfLines = 2
cell.expandButton.setTitle("Show More.", for: .normal)
let btnCell = cell
let labelIsTruncated: Bool = btnCell.titleLabel.isTruncated()
if !labelIsTruncated
btnCell.expandButton.snp.updateConstraints (make) in
make.height.equalTo(0)
btnCell.expandButton.isHidden = !labelIsTruncated
return cell
func loadLayout()
titleLabel.snp.makeConstraints (make) in
make.top.left.equalTo(15)
make.right.equalTo(-15)
expandButton.snp.makeConstraints (make) in
make.top.equalTo(titleLabel.snp.bottom).offset(10)
make.left.equalTo(10)
make.right.equalTo(-15)
make.bottom.equalTo(-15)
make.height.equalTo(100)
它有效。最后一点,您不应该在 cellDisplay 方法中更改单元格子视图的布局。
已弃用: 我认为是自动布局策略的问题,您在下面设置标签和按钮的布局:
func loadLayout()
titleLabel.snp.makeConstraints (make) in
make.top.left.equalTo(15)
make.right.equalTo(-15)
expandButton.snp.makeConstraints (make) in
make.top.equalTo(titleLabel.snp.bottom).offset(10)
make.left.equalTo(10)
make.right.equalTo(-15)
make.bottom.equalTo(-15)
它只会在单元格初始化时被调用,当你刷新tableview并设置按钮隐藏时,约束不会改变。 我建议您手动计算此单元格的高度。 当您使用自动单元格高度时,必须有一些高级方法来保持自调整大小。这部分我也在学习,等找到完美的方法再告诉你。 我希望这对你有帮助。
【讨论】:
我记得我尝试让 labelIsTruncated 在“cellForRow”中,并且 labelIsTruncated 始终为真。所以,我改为让 labelIsTruncated 在“willDisplay”中以上是关于如何更改 tableview willDisplay 函数中的布局和属性设置?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 UIViewController 中更改 TableView 的属性
如何在 swift 中更改 tableView 部分中的文本颜色