问题=味精标签未显示/正在创建
我已经提供了所有必需的东西。代码中可见的函数直接在tableview的cellforrowat函数中调用。
图像1 = [单击按钮后的层次结构视图1](https://ibb.co/QfvsV3C) 图片2 = [点击按钮之前的层次结构视图2](https://ibb.co/L0pz2kz)
msg lbl代码:
func drawMsgLbl(text: String)
{
//var msg = UILabel()
//msg = UILabel()
//msg?.lineBreakMode = .byWordWrapping
msg.numberOfLines = 0
msg.font = UIFont.init(name: "Avenir", size: 20)
msg.text = text
let txtWidth = text.size(OfFont: msg.font)
msg.textColor = .black
msg.backgroundColor = .yellow
// msg.frame = CGRect(x: 0, y: 0, width: msg.intrinsicContentSize.width, height: msg.intrinsicContentSize.height)
let constraintRect = CGSize(width: (0.66 * self.frame.width),
height: .greatestFiniteMagnitude)
let boundingBox = text.boundingRect(with: constraintRect,
options: .usesLineFragmentOrigin,
attributes: [.font: msg.font],
context: nil)
msg.frame.size = CGSize(width: ceil(boundingBox.width),
height: ceil(boundingBox.height))
print("Bounnding Width = \(boundingBox.width)")
print("msgIntrinsicWidth = \(msg.intrinsicContentSize.width)")
print("Text Width = \(txtWidth)")
print(text)
msg.frame.origin = CGPoint(x: (self.frame.size.width)-((msg.frame.size.width))-20, y: (self.frame.height)+10)
//msg?.center = self.center
let bubbleSize = CGSize(width: ((msg.frame.size.width)+30), height: ((msg.frame.size.height)+20))
let incomingBubblee = incomingBubble()
let outgoingBubblee = outgoingBubble()
outgoingBubblee.frame.size = bubbleSize
outgoingBubblee.frame.origin = CGPoint(x: (frame.size.width)-((msg.frame.size.width))-30, y: frame.size.height)
outgoingBubblee.backgroundColor = .clear
self.addSubview(outgoingBubblee)
self.addSubview(msg)
self.backgroundColor = .gray
}
我想根据使用的Bezier路径生成文本来生成带有宽度和高度的味精标签(其代码单独放置,代码工作正常)
答案 0 :(得分:1)
这是一个非常简单的示例,使用自动布局约束来允许单元格/行自动调整其高度。
全部通过代码-没有@IBOutlets
或原型单元格-因此只需将UITableViewController
分配给此类(ChatBubbleTestTableViewController
)
// simple "Message" struct
struct MyMessage {
var incoming: Bool = false
var message: String = ""
}
class ChatBubbleView: UIView {
let bubbleLayer = CAShapeLayer()
let chatLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.numberOfLines = 0
v.text = "Sample text"
return v
}()
// if it's an incoming message, background will be gray and bubble left-aligned
// otherwise background will be green and bubble right-alinged
var incoming = false
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() -> Void {
// add the bubble layer
layer.addSublayer(bubbleLayer)
// add the label
addSubview(chatLabel)
// constrain the label with 12-pts padding on all 4 sides
NSLayoutConstraint.activate([
chatLabel.topAnchor.constraint(equalTo: topAnchor, constant: 12.0),
chatLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -12.0),
chatLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 12.0),
chatLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -12.0),
])
}
override func layoutSubviews() {
super.layoutSubviews()
let width = bounds.size.width
let height = bounds.size.height
let bezierPath = UIBezierPath()
// NOTE: this bezier path is from
// https://medium.com/@dima_nikolaev/creating-a-chat-bubble-which-looks-like-a-chat-bubble-in-imessage-the-advanced-way-2d7497d600ba
if incoming {
bezierPath.move(to: CGPoint(x: 22, y: height))
bezierPath.addLine(to: CGPoint(x: width - 17, y: height))
bezierPath.addCurve(to: CGPoint(x: width, y: height - 17), controlPoint1: CGPoint(x: width - 7.61, y: height), controlPoint2: CGPoint(x: width, y: height - 7.61))
bezierPath.addLine(to: CGPoint(x: width, y: 17))
bezierPath.addCurve(to: CGPoint(x: width - 17, y: 0), controlPoint1: CGPoint(x: width, y: 7.61), controlPoint2: CGPoint(x: width - 7.61, y: 0))
bezierPath.addLine(to: CGPoint(x: 21, y: 0))
bezierPath.addCurve(to: CGPoint(x: 4, y: 17), controlPoint1: CGPoint(x: 11.61, y: 0), controlPoint2: CGPoint(x: 4, y: 7.61))
bezierPath.addLine(to: CGPoint(x: 4, y: height - 11))
bezierPath.addCurve(to: CGPoint(x: 0, y: height), controlPoint1: CGPoint(x: 4, y: height - 1), controlPoint2: CGPoint(x: 0, y: height))
bezierPath.addLine(to: CGPoint(x: -0.05, y: height - 0.01))
bezierPath.addCurve(to: CGPoint(x: 11.04, y: height - 4.04), controlPoint1: CGPoint(x: 4.07, y: height + 0.43), controlPoint2: CGPoint(x: 8.16, y: height - 1.06))
bezierPath.addCurve(to: CGPoint(x: 22, y: height), controlPoint1: CGPoint(x: 16, y: height), controlPoint2: CGPoint(x: 19, y: height))
bezierPath.close()
} else {
bezierPath.move(to: CGPoint(x: width - 22, y: height))
bezierPath.addLine(to: CGPoint(x: 17, y: height))
bezierPath.addCurve(to: CGPoint(x: 0, y: height - 17), controlPoint1: CGPoint(x: 7.61, y: height), controlPoint2: CGPoint(x: 0, y: height - 7.61))
bezierPath.addLine(to: CGPoint(x: 0, y: 17))
bezierPath.addCurve(to: CGPoint(x: 17, y: 0), controlPoint1: CGPoint(x: 0, y: 7.61), controlPoint2: CGPoint(x: 7.61, y: 0))
bezierPath.addLine(to: CGPoint(x: width - 21, y: 0))
bezierPath.addCurve(to: CGPoint(x: width - 4, y: 17), controlPoint1: CGPoint(x: width - 11.61, y: 0), controlPoint2: CGPoint(x: width - 4, y: 7.61))
bezierPath.addLine(to: CGPoint(x: width - 4, y: height - 11))
bezierPath.addCurve(to: CGPoint(x: width, y: height), controlPoint1: CGPoint(x: width - 4, y: height - 1), controlPoint2: CGPoint(x: width, y: height))
bezierPath.addLine(to: CGPoint(x: width + 0.05, y: height - 0.01))
bezierPath.addCurve(to: CGPoint(x: width - 11.04, y: height - 4.04), controlPoint1: CGPoint(x: width - 4.07, y: height + 0.43), controlPoint2: CGPoint(x: width - 8.16, y: height - 1.06))
bezierPath.addCurve(to: CGPoint(x: width - 22, y: height), controlPoint1: CGPoint(x: width - 16, y: height), controlPoint2: CGPoint(x: width - 19, y: height))
bezierPath.close()
}
bubbleLayer.fillColor = incoming ? UIColor(white: 0.90, alpha: 1.0).cgColor : UIColor.green.cgColor
bubbleLayer.path = bezierPath.cgPath
}
}
class ChatCell: UITableViewCell {
let bubbleView: ChatBubbleView = {
let v = ChatBubbleView()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
var leadingOrTrailingConstraint = NSLayoutConstraint()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() -> Void {
// add the bubble view
contentView.addSubview(bubbleView)
// constrain top / bottom with 12-pts padding
// constrain width to lessThanOrEqualTo 2/3rds (66%) of the width of the cell
NSLayoutConstraint.activate([
bubbleView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12.0),
bubbleView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12.0),
bubbleView.widthAnchor.constraint(lessThanOrEqualTo: contentView.widthAnchor, multiplier: 0.66),
])
}
func setData(_ message: MyMessage) -> Void {
// set the label text
bubbleView.chatLabel.text = message.message
// tell the bubble view whether it's an incoming or outgoing message
bubbleView.incoming = message.incoming
// left- or right-align the bubble view, based on incoming or outgoing
leadingOrTrailingConstraint.isActive = false
if message.incoming {
leadingOrTrailingConstraint = bubbleView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 12.0)
} else {
leadingOrTrailingConstraint = bubbleView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -12.0)
}
leadingOrTrailingConstraint.isActive = true
}
}
class ChatBubbleTestTableViewController: UITableViewController {
let theData: [MyMessage] = [
MyMessage(incoming: false, message: "A short message."),
MyMessage(incoming: true, message: "A medium length message, longer than short."),
MyMessage(incoming: false, message: "A long message. This one should be long enough to wrap onto multiple lines, showing that this message bubble cell will auto-size itself to the message content."),
MyMessage(incoming: true, message: "Another short message."),
MyMessage(incoming: false, message: "Another medium length message, longer than short."),
MyMessage(incoming: true, message: "Another long message. This one should be long enough to wrap onto multiple lines, showing that this message bubble cell will auto-size itself to the message content."),
]
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(ChatCell.self, forCellReuseIdentifier: "ChatCell")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return theData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ChatCell", for: indexPath) as! ChatCell
cell.setData(theData[indexPath.row])
return cell
}
}
结果:
,请注意,它会在单元格更改大小(例如旋转设备)时自动调整大小:
编辑
您的代码有问题...
在ChatCell.swift
中,您拥有:
func commonInit()
{
contentView.addSubview(bubbleView)
NSLayoutConstraint.activate([
bubbleView.topAnchor.constraint(equalTo: topAnchor, constant: 12.0),
bubbleView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -12.0),
bubbleView.widthAnchor.constraint(lessThanOrEqualTo: contentView.widthAnchor, multiplier: 0.66)
])
}
bubbleView
需要限制在单元格的contentView
中:
func commonInit()
{
contentView.addSubview(bubbleView)
NSLayoutConstraint.activate([
bubbleView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12.0),
bubbleView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12.0),
bubbleView.widthAnchor.constraint(lessThanOrEqualTo: contentView.widthAnchor, multiplier: 0.66)
])
}
编辑2
更改气泡背景颜色的最直接方法...
在ChatBubbleView
类中,删除此行(在layoutSubviews()
的末尾:
bubbleLayer.fillColor = isIncoming ? UIColor(white: 0.90, alpha: 1.0).cgColor : UIColor.green.cgColor
在ChatCell
类中,添加两个属性:
var incomingColor: UIColor = UIColor(white: 0.90, alpha: 1.0)
var outgoingColor: UIColor = UIColor.green
这些将是您的“默认”颜色。
也在ChatCell
类的setData()
中,添加以下行:
bubbleView.bubbleLayer.fillColor = message.incoming ? incomingColor.cgColor : outgoingColor.cgColor
然后,在TestVC
的{{1}}中,您可以执行以下操作:
cellForRowAt
我将取决于您要如何实现用户的颜色选择。