在 tableView 单元格上添加子视图会导致可悲的拼凑
Add subview on tableView cells causes a sad patchwork
我想在我的 iPhone 应用程序中为 table 消息视图提供聊天功能。
为了执行高质量的渲染,我添加了两个子视图:文本和 "container" 这只是一个具有背景颜色的视图。
即使它第一次工作,当我滚动时,它变得非常混乱,因为它不断添加很多子视图。
这里是处理变换的函数,它在滚动时调用。
func configChatCell(cell: UITableViewCell, text: String, color:UIColor)
{
cell.textLabel?.numberOfLines = 0
cell.textLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
cell.textLabel?.textColor = UIColor.whiteColor()
let fixedWidth = cell.bounds.width - 150
let textView: UITextView = UITextView(frame: CGRect(x: 0, y: 0, width: 10, height: CGFloat.max))
textView.text = text
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
var newFrame = textView.frame
newFrame.size = CGSize(width: min(newSize.width, fixedWidth), height: newSize.height)
textView.sizeThatFits(newFrame.size)
textView.frame = newFrame
textView.backgroundColor = UIColor.clearColor()
self.rowHeight = textView.frame.height+20
let view = UIView()
view.backgroundColor = color
print(textView.frame.height+10)
view.frame = CGRect(x: 0, y: 5, width: textView.frame.width+50, height: textView.frame.height+10)
view.layer.cornerRadius = 5
cell.backgroundColor = UIColor.clearColor()
cell.contentView.addSubview(view)
cell.contentView.addSubview(textView)
cell.contentView.sendSubviewToBack(view)
}
如果我每次滚动时都删除子视图,则屏幕上不会显示任何内容。
有人可以帮我找到解决办法吗?或者还有其他方法吗?
提前致谢!
假设你的configureChatCell
是从tableView:cellForRowAtIndexPath:
调用的,那么@Paulw11是对的;单元格被重复使用,因此您应该只对 table 中的该行进行更改 。在您的示例中,您应该在方法中进行的 only 调用是 textView.text = text
以及调整 textView
大小以适应的调用。其他一切都应该放在情节提要中的动态单元原型中,或者,如果你想在代码中做所有事情(我有一种不好的感觉),然后将其余配置放在 UITableViewCell
子类中,然后使用您的 table 视图注册该子类。
我很快为此写了一些东西。
它以 ChatCell
开头
class ChatCell: UITableViewCell {
var messageLabel: UILabel? {
didSet {
messageLabel?.text = message
}
}
var message: String? {
didSet {
messageLabel?.text = message
}
}
class func messageCell(withText text: String, leading: Bool = true) -> ChatCell {
let cell = ChatCell()
cell.message = text
// Make the container
let container = UIView()
container.translatesAutoresizingMaskIntoConstraints = false
cell.contentView.addSubview(container)
container.topAnchor.constraintEqualToAnchor(cell.contentView.topAnchor, constant: 8).active = true
container.bottomAnchor.constraintEqualToAnchor(cell.contentView.bottomAnchor, constant: -8).active = true
if leading {
container.leadingAnchor.constraintEqualToAnchor(cell.contentView.leadingAnchor, constant: leading ? 8 : 8*8).active = true
container.trailingAnchor.constraintLessThanOrEqualToAnchor(cell.contentView.trailingAnchor, constant: leading ? -8*8 : -8).active = true
} else {
container.leadingAnchor.constraintGreaterThanOrEqualToAnchor(cell.contentView.leadingAnchor, constant: leading ? 8 : 8*8).active = true
container.trailingAnchor.constraintEqualToAnchor(cell.contentView.trailingAnchor, constant: leading ? -8*8 : -8).active = true
}
// Make the messageLabel.
let messageLabel = UILabel()
messageLabel.numberOfLines = 0
messageLabel.textColor = UIColor.whiteColor()
messageLabel.translatesAutoresizingMaskIntoConstraints = false
container.addSubview(messageLabel)
// Add constraints.
messageLabel.topAnchor.constraintEqualToAnchor(container.topAnchor, constant: 8).active = true
messageLabel.bottomAnchor.constraintEqualToAnchor(container.bottomAnchor, constant: -8).active = true
messageLabel.leadingAnchor.constraintEqualToAnchor(container.leadingAnchor, constant: 8).active = true
messageLabel.trailingAnchor.constraintEqualToAnchor(container.trailingAnchor, constant: -8).active = true
cell.messageLabel = messageLabel
container.backgroundColor = UIColor(red:0.19, green:0.70, blue:1.00, alpha:1.00)
container.layer.cornerRadius = 12.0
return cell
}
}
该单元格还包括对前导和尾随消息以及来回对话的支持。也许像这样制作一个元组数组:
let messages: [(message: String, leading: Bool)] = [("Hello", true), ("My name is John Doe and this works quite well", false), ("I would agree", true)]
然后在您的 tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
中您可以这样做:
let cell = ChatCell.messageCell(withText: messages[indexPath.row].message, leading: messages[indexPath.row].leading)
return cell
让我知道这是否适合您。我在 Playground 中对其进行了测试,它按预期工作
我写的是这样的。很简单,但可以阐明解决方案
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseid", forIndexPath: indexPath)
// Configure the cell...
let contentView = cell.contentView
let subviews = contentView.subviews
for view in subviews {
if 100 == view.tag {
let label = view as! UILabel
label.text = self.datas[indexPath.row]
} else if 200 == view.tag {
view.layer.cornerRadius = 10.0
}
}
return cell
}
关键是配置tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
中的每一件事
代码中带有标签 200 的视图是一个背景视图,与标签具有相同的框架,我在情节提要中使用布局约束来确保其大小和位置。
我想在我的 iPhone 应用程序中为 table 消息视图提供聊天功能。 为了执行高质量的渲染,我添加了两个子视图:文本和 "container" 这只是一个具有背景颜色的视图。
即使它第一次工作,当我滚动时,它变得非常混乱,因为它不断添加很多子视图。
这里是处理变换的函数,它在滚动时调用。
func configChatCell(cell: UITableViewCell, text: String, color:UIColor)
{
cell.textLabel?.numberOfLines = 0
cell.textLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
cell.textLabel?.textColor = UIColor.whiteColor()
let fixedWidth = cell.bounds.width - 150
let textView: UITextView = UITextView(frame: CGRect(x: 0, y: 0, width: 10, height: CGFloat.max))
textView.text = text
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
var newFrame = textView.frame
newFrame.size = CGSize(width: min(newSize.width, fixedWidth), height: newSize.height)
textView.sizeThatFits(newFrame.size)
textView.frame = newFrame
textView.backgroundColor = UIColor.clearColor()
self.rowHeight = textView.frame.height+20
let view = UIView()
view.backgroundColor = color
print(textView.frame.height+10)
view.frame = CGRect(x: 0, y: 5, width: textView.frame.width+50, height: textView.frame.height+10)
view.layer.cornerRadius = 5
cell.backgroundColor = UIColor.clearColor()
cell.contentView.addSubview(view)
cell.contentView.addSubview(textView)
cell.contentView.sendSubviewToBack(view)
}
如果我每次滚动时都删除子视图,则屏幕上不会显示任何内容。
有人可以帮我找到解决办法吗?或者还有其他方法吗?
提前致谢!
假设你的configureChatCell
是从tableView:cellForRowAtIndexPath:
调用的,那么@Paulw11是对的;单元格被重复使用,因此您应该只对 table 中的该行进行更改 。在您的示例中,您应该在方法中进行的 only 调用是 textView.text = text
以及调整 textView
大小以适应的调用。其他一切都应该放在情节提要中的动态单元原型中,或者,如果你想在代码中做所有事情(我有一种不好的感觉),然后将其余配置放在 UITableViewCell
子类中,然后使用您的 table 视图注册该子类。
我很快为此写了一些东西。
它以 ChatCell
class ChatCell: UITableViewCell {
var messageLabel: UILabel? {
didSet {
messageLabel?.text = message
}
}
var message: String? {
didSet {
messageLabel?.text = message
}
}
class func messageCell(withText text: String, leading: Bool = true) -> ChatCell {
let cell = ChatCell()
cell.message = text
// Make the container
let container = UIView()
container.translatesAutoresizingMaskIntoConstraints = false
cell.contentView.addSubview(container)
container.topAnchor.constraintEqualToAnchor(cell.contentView.topAnchor, constant: 8).active = true
container.bottomAnchor.constraintEqualToAnchor(cell.contentView.bottomAnchor, constant: -8).active = true
if leading {
container.leadingAnchor.constraintEqualToAnchor(cell.contentView.leadingAnchor, constant: leading ? 8 : 8*8).active = true
container.trailingAnchor.constraintLessThanOrEqualToAnchor(cell.contentView.trailingAnchor, constant: leading ? -8*8 : -8).active = true
} else {
container.leadingAnchor.constraintGreaterThanOrEqualToAnchor(cell.contentView.leadingAnchor, constant: leading ? 8 : 8*8).active = true
container.trailingAnchor.constraintEqualToAnchor(cell.contentView.trailingAnchor, constant: leading ? -8*8 : -8).active = true
}
// Make the messageLabel.
let messageLabel = UILabel()
messageLabel.numberOfLines = 0
messageLabel.textColor = UIColor.whiteColor()
messageLabel.translatesAutoresizingMaskIntoConstraints = false
container.addSubview(messageLabel)
// Add constraints.
messageLabel.topAnchor.constraintEqualToAnchor(container.topAnchor, constant: 8).active = true
messageLabel.bottomAnchor.constraintEqualToAnchor(container.bottomAnchor, constant: -8).active = true
messageLabel.leadingAnchor.constraintEqualToAnchor(container.leadingAnchor, constant: 8).active = true
messageLabel.trailingAnchor.constraintEqualToAnchor(container.trailingAnchor, constant: -8).active = true
cell.messageLabel = messageLabel
container.backgroundColor = UIColor(red:0.19, green:0.70, blue:1.00, alpha:1.00)
container.layer.cornerRadius = 12.0
return cell
}
}
该单元格还包括对前导和尾随消息以及来回对话的支持。也许像这样制作一个元组数组:
let messages: [(message: String, leading: Bool)] = [("Hello", true), ("My name is John Doe and this works quite well", false), ("I would agree", true)]
然后在您的 tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
中您可以这样做:
let cell = ChatCell.messageCell(withText: messages[indexPath.row].message, leading: messages[indexPath.row].leading)
return cell
让我知道这是否适合您。我在 Playground 中对其进行了测试,它按预期工作
我写的是这样的。很简单,但可以阐明解决方案
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseid", forIndexPath: indexPath)
// Configure the cell...
let contentView = cell.contentView
let subviews = contentView.subviews
for view in subviews {
if 100 == view.tag {
let label = view as! UILabel
label.text = self.datas[indexPath.row]
} else if 200 == view.tag {
view.layer.cornerRadius = 10.0
}
}
return cell
}
关键是配置tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
中的每一件事
代码中带有标签 200 的视图是一个背景视图,与标签具有相同的框架,我在情节提要中使用布局约束来确保其大小和位置。