我正在处理带有消息气泡的聊天应用。我已经弄清楚如何根据发送消息的人来获取有条件格式化的消息(颜色,大小等);但是我很难让聊天气泡与视图控制器的左侧或右侧对齐。现在所有项目都对齐到左边。我搜索过SO而无法找到答案所以我决定问一下。
更新:显示setCell函数的剩余代码,该函数根据'incoming'的值确定消息的格式。还包括tableView函数以显示单元格配置。最后一个功能是设置功能。</ p>
func setCell(cell: ConversationCell, incoming: [Int], indexPath: IndexPath) {
var layoutAttribute: NSLayoutAttribute
var layoutConstant: CGFloat
var smavalayoutConstant: CGFloat
for i in 0 ..< self.incoming.count {
if (self.incoming[indexPath.row] == 1) {
cell.bubbleImageView.image=#imageLiteral(resourceName: "chat_bubble_received")
cell.messageLbl.textColor = UIColor.black
cell.messageLbl.textAlignment = .left
cell.messageLbl?.numberOfLines = 0
cell.messageLbl?.lineBreakMode = .byWordWrapping
layoutAttribute = .left
layoutConstant = 0
cell.contentView.addConstraint(NSLayoutConstraint(item: cell.bubbleImageView, attribute: .left, relatedBy: .equal, toItem: cell.contentView, attribute: layoutAttribute, multiplier: 1, constant: layoutConstant))
cell.contentView.addConstraint(NSLayoutConstraint(item: cell.smavaImg, attribute: .left, relatedBy: .equal, toItem: cell.contentView, attribute: layoutAttribute, multiplier: 1, constant: layoutConstant))
cell.contentView.addConstraint(NSLayoutConstraint(item: cell.postpictureImg, attribute: .left, relatedBy: .equal, toItem: cell.contentView, attribute: layoutAttribute, multiplier: 1, constant: layoutConstant))
}
if (self.incoming[indexPath.row] == 0) {
cell.bubbleImageView.image = #imageLiteral(resourceName: "chat_bubble_sent")
cell.messageLbl.textColor = UIColor.white
cell.messageLbl.textAlignment = .right
layoutAttribute = .right
layoutConstant = -100
smavalayoutConstant = 300
cell.contentView.addConstraint(NSLayoutConstraint(item: cell.bubbleImageView, attribute: .leftMargin, relatedBy: .lessThanOrEqual, toItem: cell.contentView, attribute: layoutAttribute, multiplier: 1, constant: layoutConstant))
cell.contentView.addConstraint(NSLayoutConstraint(item: cell.bubbleImageView, attribute: .right, relatedBy: .equal, toItem: cell.contentView, attribute: layoutAttribute, multiplier: 1, constant: layoutConstant))
cell.contentView.addConstraint(NSLayoutConstraint(item: cell.smavaImg, attribute: .right, relatedBy: .equal, toItem: cell.smavaImg, attribute: layoutAttribute, multiplier: 1, constant: smavalayoutConstant))
cell.contentView.addConstraint(NSLayoutConstraint(item: cell.smavaImg, attribute: .left, relatedBy: .equal, toItem: cell.smavaImg, attribute: .left, multiplier: 1, constant: 300))
}
}
}
// cell config
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ConversationCell
// shortcuts
let hhpost = hhmessages[indexPath.row]
let image = avas[indexPath.row]
let smimages = images[indexPath.row]
let messagetext = hhpost["messagetext"] as? String
let date = hhpost["date"] as? String
cell.messageLbl.text = messagetext
cell.dateLbl.text = date
cell.smavaImg.image = image
cell.postpictureImg.image = smimages
DispatchQueue.main.async {
tableView.transform = CGAffineTransform(rotationAngle: -CGFloat.pi)
cell.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
self.setCell(cell: cell, incoming: self.incoming, indexPath: indexPath)
}
return cell
}
public func setup() {
bubbleImageView = UIImageView(image: #imageLiteral(resourceName: "chat_bubble_sent"), highlightedImage: #imageLiteral(resourceName: "chat_bubble_sent"))
bubbleImageView.isUserInteractionEnabled = true
messageLbl = UILabel(frame: CGRect.zero)
messageLbl.font = UIFont.systemFont(ofSize: 15)
messageLbl.numberOfLines = 0
messageLbl.isUserInteractionEnabled = true
selectionStyle = .none
contentView.addSubview(bubbleImageView)
contentView.addSubview(smavaImg)
bubbleImageView.addSubview(messageLbl)
messageLbl.translatesAutoresizingMaskIntoConstraints = false
bubbleImageView.translatesAutoresizingMaskIntoConstraints = false
contentView.addConstraint(NSLayoutConstraint(item: bubbleImageView, attribute: .left, relatedBy: .equal, toItem: contentView, attribute: .left, multiplier: 1, constant: 10))
contentView.addConstraint(NSLayoutConstraint(item: bubbleImageView, attribute: .top, relatedBy: .equal, toItem: contentView, attribute: .top, multiplier: 1, constant: 4.5))
bubbleImageView.addConstraint(NSLayoutConstraint(item: bubbleImageView, attribute: .width, relatedBy: .equal, toItem: messageLbl, attribute: .width, multiplier: 1, constant: 30))
contentView.addConstraint(NSLayoutConstraint(item: bubbleImageView, attribute: .bottom, relatedBy: .equal, toItem: contentView, attribute: .bottom, multiplier: 1, constant: -4.5))
bubbleImageView.addConstraint(NSLayoutConstraint(item: messageLbl, attribute: .centerX, relatedBy: .equal, toItem: bubbleImageView, attribute: .centerX, multiplier: 1, constant: -2))
bubbleImageView.addConstraint(NSLayoutConstraint(item: messageLbl, attribute: .centerY, relatedBy: .equal, toItem: bubbleImageView, attribute: .centerY, multiplier: 1, constant: -0.5))
messageLbl.preferredMaxLayoutWidth = 218
bubbleImageView.addConstraint(NSLayoutConstraint(item: messageLbl, attribute: .height, relatedBy: .equal, toItem: bubbleImageView, attribute: .height, multiplier: 1, constant: -15))
contentView.addConstraint(NSLayoutConstraint(item: smavaImg, attribute: .centerX, relatedBy: .equal, toItem: smavaImg, attribute: .centerX, multiplier: 1, constant: -2))
contentView.addConstraint(NSLayoutConstraint(item: smavaImg, attribute: .centerY, relatedBy: .equal, toItem: smavaImg, attribute: .centerY, multiplier: 1, constant: -0.5))
}
答案 0 :(得分:1)
在我的游乐场中查看我的git hub项目 // Maximo Lucosi:https://github.com/lucosi/ChatTableView 您可以使用所有约束创建tableViewCell并更改单元格内的约束。 在Playgournd中打开项目&gt;查看&gt;助理编辑&gt;显示助理编辑器
class MyViewController:UIViewController {
// Messages for test
var messages: [Message] = []
// Table View here + basic configuration
lazy var tableView: UITableView = {
let view = UITableView()
view.translatesAutoresizingMaskIntoConstraints = false
view.delegate = self
view.dataSource = self
view.backgroundColor = .white
view.separatorStyle = .none
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
// Set the screen size befor implement layour. NOTICE: Only for playground test
self.view.frame = frame
// Messages for test //
self.messages.append(Message.init(message: "I'm working on a chat app with message bubbles.",
image: UIImage.init(),
incoming: 0))
self.messages.append(Message.init(message: "What is your dificulte.",
image: UIImage(),
incoming: 1))
self.messages.append(Message.init(message: "I'm having difficulty getting the chat bubbles to align to the left or right side of the view controller.",
image: UIImage.init(),
incoming: 0))
self.messages.append(Message.init(message: "One more for me",
image: UIImage(),
incoming: 1))
self.messages.append(Message.init(message: "I have already implemented a function that redraws UILabels with a passed ratio. So all I need to find is the text in UILabel from my view that would require the maximum ratio to redraw UILabels. So finally I need to do something like this:",
image: UIImage(), incoming: 1))
// End //
// Add the tableView
self.view.addSubview(tableView)
// Register teh cell in the tableView
self.tableView.register(ConversationCell.self, forCellReuseIdentifier: cellId)
// Criate a contraint for the table view
NSLayoutConstraint.activate(
[
tableView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 44),
tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)
]
)
}
}
extension String {
//* Calculeta the hight string Function
func calculateTextFrameRect(
objectsInPlaceHeight: CGFloat,
objectsInPlaceWidth: CGFloat,
fontSize: CGFloat,
fontWeight: CGFloat) -> CGSize
{
let bounding = CGSize(width: UIScreen.main.bounds.width - objectsInPlaceWidth, height: .infinity)
let rect = NSString(string: self).boundingRect(
with: bounding,
options: NSStringDrawingOptions.usesFontLeading.union(NSStringDrawingOptions.usesLineFragmentOrigin),
attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: fontSize, weight: UIFont.Weight(rawValue: fontWeight))],
context: nil)
return CGSize(width: UIScreen.main.bounds.width, height: rect.height + objectsInPlaceHeight )
}
}
//使用委托和数据源符合表视图 扩展MyViewController:UITableViewDelegate,UITableViewDataSource {
// Change the hight of the cell
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// Calculate the hight of the cell
let text = self.messages[indexPath.item].message
let frameSize = text.calculateTextFrameRect(
objectsInPlaceHeight: 44 + 10,
objectsInPlaceWidth: 20 + 44 + 20 + self.view.frame.width * 0.4,
fontSize: UIFont.preferredFont(forTextStyle: UIFontTextStyle.body).pointSize,
fontWeight: UIFont.Weight.medium.rawValue)
return frameSize.height
}
// Number os cells
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.messages.count
}
// Return cell to display on the tableView
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! ConversationCell
cell.messageData = self.messages[indexPath.item]
return cell
}
}
// ******自定义单元格类/// class ConversationCell:UITableViewCell {
var messageData: Message? {
didSet {
// Umrap the value incide the cell
if let message = messageData {
// Confiture the constraints for cell
if message.incoming == 0 {
// Text
self.messageTextView.textAlignment = .left
self.bubleImage.backgroundColor = .orange
// Constraints
self.lefBubleConstraint.isActive = true
self.rightBubleConstraint.isActive = false
} else {
// Text
self.messageTextView.textAlignment = .right
self.bubleImage.backgroundColor = .blue
// Constraints
self.lefBubleConstraint.isActive = false
self.rightBubleConstraint.isActive = true
}
if lefBubleConstraint.isActive == true {
self.leftMessageLable.isActive = true
self.rightMessageLable.isActive = false
} else {
self.leftMessageLable.isActive = false
self.rightMessageLable.isActive = true
}
// Set the data
self.messageTextView.text = message.message
self.bubleImage.image = message.image
}
}
}
// Create and config the image
let bubleImage: UIImageView = {
let view = UIImageView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .blue
view.layer.cornerRadius = 22
view.layer.masksToBounds = true
return view
}()
// Create and config the lable for the text
let messageTextView: UITextView = {
let view = UITextView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.lightGray.withAlphaComponent(0.5)
view.layer.cornerRadius = 10
view.textContainerInset = UIEdgeInsetsMake(5, 5, 5, 5)
view.isUserInteractionEnabled = false
return view
}()
// Constraints for configuration on didSet data
var lefBubleConstraint: NSLayoutConstraint!
var rightBubleConstraint: NSLayoutConstraint!
var leftMessageLable: NSLayoutConstraint!
var rightMessageLable: NSLayoutConstraint!
// Init the cell with local congiguration
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: nil)
self.addSubview(bubleImage)
self.addSubview(messageTextView)
// Permanent constraints
NSLayoutConstraint.activate(
[
self.bubleImage.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10),
self.bubleImage.heightAnchor.constraint(equalToConstant: 44),
self.bubleImage.widthAnchor.constraint(equalToConstant: 44),
self.messageTextView.topAnchor.constraint(equalTo: self.topAnchor, constant: 10),
self.messageTextView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10),
// NOTICE: Use the frame with as parameter for mesure the hight of cell on the main view
self.messageTextView.widthAnchor.constraint(equalToConstant: self.frame.width * 0.7)
]
)
// Buble constraint for configuration
self.lefBubleConstraint = self.bubleImage.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10)
self.rightBubleConstraint = self.bubleImage.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10)
// Message constrait for congiguration
self.rightMessageLable = self.messageTextView.rightAnchor.constraint(equalTo: self.bubleImage.leftAnchor, constant: -10)
self.leftMessageLable = self.messageTextView.leftAnchor.constraint(equalTo: self.bubleImage.rightAnchor, constant: 10)
}
// requerid init
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}