为啥我的 UITableView 单元格在滚动时重叠?
Posted
技术标签:
【中文标题】为啥我的 UITableView 单元格在滚动时重叠?【英文标题】:Why do my UITableView cells overlap on scroll?为什么我的 UITableView 单元格在滚动时重叠? 【发布时间】:2020-06-12 21:20:59 【问题描述】:我以编程方式创建了一个基本的 ios 应用程序(删除了情节提要)。我还创建了一个带有自定义 UITableViewCell 的 UITableView,并以编程方式设置了约束。在我向下滚动表格视图之前,表格视图的行看起来应该是这样的。但是当我滚动时,它们重叠并且事情变得奇怪。
这是滚动之前的样子: click here for image of app before scrolling
这是应用滚动后的样子:click here for image of app after scrolling
我尝试设置行高,并在单元格和表格视图上使用 clipsToBounds 属性。这是管理 UITableView 的视图控制器的一部分代码:
class SocialFeedVC: UIViewController
let tableView = UITableView()
view.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
tableView.allowsSelection = false
tableView.showsVerticalScrollIndicator = false
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.topAnchor.constraint(equalTo: teamSelectorContainer.bottomAnchor, constant: 3.5).isActive = true
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
tableView.register(SocialFeedPostCell.self, forCellReuseIdentifier: cellName)
extension SocialFeedVC: UITableViewDelegate, UITableViewDataSource
// Define amount of rows in table view
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return feedPosts.count
// Define each cell in table view
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: cellName) as! SocialFeedPostCell
let feedPost = feedPosts[indexPath.row]
cell.set(feedPost: feedPost)
return cell
我的表格单元格代码也在下面,但由于采用程序化路线而有点长。随意看看你想要什么。
import UIKit
class SocialFeedPostCell: UITableViewCell
let nameLabel = UILabel()
let postCreationTimeLabel = UILabel()
let profilePhoto = UIImageView()
// Needed with programmatic method
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?)
super.init(style: style, reuseIdentifier: reuseIdentifier)
configureProfilePhoto()
configureNameLabel()
configrePostCreationTimeLabel()
required init?(coder: NSCoder)
fatalError("init(coder:) has not been implemented")
// Update view with controller information accordingly
func set(feedPost: FeedPost)
nameLabel.text = feedPost.nameOfPoster
postCreationTimeLabel.text = feedPost.creationTimestamp
profilePhoto.image = UIImage(named: feedPost.profilePhoto)
// Create post depending on type
if (feedPost.content.type == PostType.text)
let contentLabel: UILabel =
let label = UILabel()
label.numberOfLines = 5
label.font = Probook.paragraph
label.lineBreakMode = .byTruncatingTail
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 2.5
paragraphStyle.lineBreakMode = .byTruncatingTail
let attrString = NSMutableAttributedString(string: feedPost.content.text!)
attrString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range:NSMakeRange(0, attrString.length))
label.attributedText = attrString
return label
()
// Add to subview and provide constraints
addSubview(contentLabel)
contentLabel.translatesAutoresizingMaskIntoConstraints = false
contentLabel.topAnchor.constraint(equalTo: postCreationTimeLabel.bottomAnchor, constant: 15).isActive = true
contentLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -17.5).isActive = true
contentLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10).isActive = true
contentLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10).isActive = true
else if (feedPost.content.type == PostType.image)
// Create image caption
let imageCaptionLabel: UILabel =
let caption = UILabel()
caption.numberOfLines = 5
caption.font = Probook.paragraph
caption.lineBreakMode = .byTruncatingTail
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 2.5
paragraphStyle.lineBreakMode = .byTruncatingTail
let attrString = NSMutableAttributedString(string: feedPost.content.imageCaption!)
attrString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range:NSMakeRange(0, attrString.length))
caption.attributedText = attrString
return caption
()
// Add to subview and provide constraints
addSubview(imageCaptionLabel)
imageCaptionLabel.translatesAutoresizingMaskIntoConstraints = false
imageCaptionLabel.topAnchor.constraint(equalTo: postCreationTimeLabel.bottomAnchor, constant: 15).isActive = true
imageCaptionLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10).isActive = true
imageCaptionLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10).isActive = true
// Create image
let imageView: UIImageView =
let image = UIImage(named: "chase")
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFit
imageView.clipsToBounds = true
imageView.layer.masksToBounds = true
return imageView
()
// Add to subview and provide constraints
addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.topAnchor.constraint(equalTo: imageCaptionLabel.bottomAnchor, constant: 15).isActive = true
imageView.heightAnchor.constraint(equalToConstant: 50).isActive = true
imageView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
imageView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
imageView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
func configureProfilePhoto()
addSubview(profilePhoto)
profilePhoto.contentMode = .scaleAspectFill
profilePhoto.translatesAutoresizingMaskIntoConstraints = false
profilePhoto.widthAnchor.constraint(equalToConstant: 45).isActive = true
profilePhoto.heightAnchor.constraint(equalToConstant: 45).isActive = true
profilePhoto.layer.cornerRadius = 25
profilePhoto.clipsToBounds = true
profilePhoto.topAnchor.constraint(equalTo: topAnchor, constant: 17.5).isActive = true
profilePhoto.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20).isActive = true
func configureNameLabel()
addSubview(nameLabel)
nameLabel.numberOfLines = 0
nameLabel.adjustsFontSizeToFitWidth = true
nameLabel.font = Probook.h2
nameLabel.translatesAutoresizingMaskIntoConstraints = false
nameLabel.leadingAnchor.constraint(equalTo: profilePhoto.trailingAnchor, constant: 20).isActive = true
nameLabel.centerYAnchor.constraint(equalTo: profilePhoto.centerYAnchor).isActive = true
func configrePostCreationTimeLabel()
addSubview(postCreationTimeLabel)
postCreationTimeLabel.numberOfLines = 0
postCreationTimeLabel.adjustsFontSizeToFitWidth = true
postCreationTimeLabel.font = Probook.timestamp
postCreationTimeLabel.translatesAutoresizingMaskIntoConstraints = false
postCreationTimeLabel.topAnchor.constraint(equalTo: nameLabel.bottomAnchor).isActive = true
postCreationTimeLabel.leadingAnchor.constraint(equalTo: nameLabel.leadingAnchor).isActive = true
【问题讨论】:
请附上您的手机号码 已添加单元格代码 不要在集合调用中添加标签...因为当单元格重用时它们不会删除它们...e 【参考方案1】:它们没有“重叠”。问题是您忘记了单元是重用。因此,以前说“我在发帖”但现在说“Sivan 月”的单元格现在说 both,因为添加新文本时不会删除旧文本。当单元格位于不同行时,您将视图放置在您添加的现有视图上。
【讨论】:
在这种情况下删除以前的文本的常规方法是什么? 哦,你只需要看看你是否已经添加了标签。如果有,请不要再次添加;重复使用您已添加的现有标签。或者,在添加新标签之前始终查找标签并将其删除。只要确保只有一个!对于图像也是如此;不要只是将图像添加到需要它的行中,而是从不需要它的行中删除它。 一个非常简单的方法是实现prepareForReuse
以摆脱一切。现在当set(feedPost:)
出现时,我们从一个空单元格开始。
我在调用 set 之前使用了你的一个想法来删除所有内容 - 就像一个魅力。我只是更改了 set 函数,否则我将使用 prepareForReuse。非常感谢!
干得好!欢迎来到可重复使用细胞的世界! :)以上是关于为啥我的 UITableView 单元格在滚动时重叠?的主要内容,如果未能解决你的问题,请参考以下文章
uitableview 自定义单元格在向下滚动 uitableview 时丢失其内容
UITableView 选定的单元格在滚动时不会保持选中状态