Swift中UITableViewCell内TextView仅显示一行的解决方法求助
Swift UITableViewCell中UITextView无法自动换行的问题解决
问题描述
开发中遇到评论文本仅显示一行的问题:输入commentText时,内容无法自动换行展示。已在DetailVC的setup()中配置自动行高:
self.tableView.rowHeight = UITableView.automaticDimension self.tableView.estimatedRowHeight = UITableView.automaticDimension
同时实现了代理方法返回自动高度:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return UITableView.automaticDimension }
但自定义DetailCell内的commnetTextLabel(UITextView)仍只显示一行内容。
相关代码
DetailCell代码
import Foundation import UIKit class DetailCell: UITableViewCell { var comment: Comment? { didSet { guard let user = comment?.user else { return } guard let profileImageUrl = user.profileImageUrl else { return } guard let commentText = comment?.commentText else { return } guard let username = user.name else { return } profileImageView.loadImage(with: profileImageUrl) let attributedText = NSMutableAttributedString(string: username, attributes: [NSMutableAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 14)]) attributedText.append(NSAttributedString(string: " \(commentText)", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12)])) attributedText.append(NSAttributedString(string: " 2d.", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12), NSAttributedString.Key.foregroundColor: UIColor.lightGray])) commnetTextLabel.attributedText = attributedText } } let profileImageView: UIImageView = { let imageView = UIImageView() imageView.contentMode = .scaleToFill imageView.clipsToBounds = true imageView.backgroundColor = .lightGray return imageView }() let commnetTextLabel: UITextView = { let tv = UITextView() tv.font = UIFont.systemFont(ofSize: 12) tv.isScrollEnabled = false return tv }() let separatorView: UIView = { let view = UIView() view.backgroundColor = UIColor.lightGray return view }() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) addSubview(self.profileImageView) profileImageView.anchor(top: topAnchor, left: leftAnchor, bottom: nil, right: nil, paddingTop: 15, paddingLeft: 14, paddingBottom: 0, paddingRight: 0, width: 40, height: 40) profileImageView.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true profileImageView.layer.cornerRadius = 40 / 2 addSubview(commnetTextLabel) commnetTextLabel.anchor(top: topAnchor, left: profileImageView.rightAnchor, bottom: nil, right: rightAnchor, paddingTop: 14, paddingLeft: 8, paddingBottom: 8, paddingRight: 0, width: 0, height: 0) commnetTextLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
DetailVC代码
class DetailVC: UIViewController { let tableView = UITableView(frame: CGRect.zero, style: .grouped) var comments = [Comment]() var postId: String? } extension DetailVC: UITableViewDataSource, UITableViewDelegate { func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return UITableView.automaticDimension } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "DetailCell") as! DetailCell cell.comment = comments[indexPath.item] return cell } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { comments.count } func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: "DetailContentView") as! DetailContentView return view } func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return 150 } }
问题原因及解决方法
核心问题
- 垂直居中约束限制高度扩展:给
commnetTextLabel添加了centerYAnchor.constraint(equalTo: self.centerYAnchor),这个约束强制文本视图垂直居中,导致文本视图无法根据内容高度自动拉伸,只能显示一行。 - 缺少底部约束关联:
commnetTextLabel只设置了顶部约束,没有和cell的底部建立约束关联,cell无法感知文本视图的高度变化,无法自动调整行高。
修改代码
调整DetailCell的初始化方法,移除无效约束并添加正确的底部关联:
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) addSubview(self.profileImageView) profileImageView.anchor(top: topAnchor, left: leftAnchor, bottom: nil, right: nil, paddingTop: 15, paddingLeft: 14, paddingBottom: 0, paddingRight: 0, width: 40, height: 40) profileImageView.layer.cornerRadius = 40 / 2 // 移除头像的centerY约束,改为让头像顶部与cell顶部对齐,随cell高度变化自然适应 addSubview(commnetTextLabel) // 修改文本视图约束:关联底部到cell底部,设置合适的底部内边距,移除centerY约束 commnetTextLabel.anchor(top: topAnchor, left: profileImageView.rightAnchor, bottom: bottomAnchor, right: rightAnchor, paddingTop: 14, paddingLeft: 8, paddingBottom: 14, paddingRight: 14, width: 0, height: 0) }
额外优化
- 给
commnetTextLabel添加tv.isEditable = false,避免用户误编辑 - 可选:设置文本容器内边距为0,让布局更紧凑:
let commnetTextLabel: UITextView = { let tv = UITextView() tv.font = UIFont.systemFont(ofSize: 12) tv.isScrollEnabled = false tv.isEditable = false tv.textContainerInset = .zero tv.textContainer.lineFragmentPadding = 0 return tv }()
内容的提问来源于stack exchange,提问作者김범석
相关产品推荐
相关产品推荐

