在 Swift 中以编程方式将 UIImageView 左右对齐
Posted
技术标签:
【中文标题】在 Swift 中以编程方式将 UIImageView 左右对齐【英文标题】:Aligning UIImageView to the left and right programmatically in Swift 【发布时间】:2018-04-13 02:29:15 【问题描述】:我正在开发一个带有消息气泡的聊天应用程序。我已经弄清楚了如何根据发送消息的人有条件地格式化消息(颜色、大小等);但是我很难让聊天气泡与视图控制器的左侧或右侧对齐。现在所有项目都向左对齐。我已经搜索过 SO 并且无法找到答案,所以我决定问。
更新:显示 setCell 函数的剩余代码,该函数根据“传入”的值确定消息的格式。还包括 tableView 功能以显示单元格配置。最后一个函数是设置函数。
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))
//单元配置
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))
【问题讨论】:
你可以阅读如何做,或者使用这个框架github.com/MessageKit/MessageKit或者这个github.com/jessesquires/JSQMessagesViewController 您是否以编程方式创建了单元格视图? @maximo 我实际上是在情节提要中创建了它,但其余的自定义是通过编程完成的 @techgirl 你用的是collectionView、tableView还是scrollView?在将单元格返回到 CollectionView 或 TableView 之前在单元格内创建约束不是一个好方法。相反,最好在单元格内创建约束并在返回单元格以显示在 CollectionView 或 TableView 控制器中之前更改参数。给我更多关于你的项目的信息,我会尽力帮助你解决这个问题。 @maximo 非常感谢。我正在使用表格视图。我列出的代码位于使用单元格参数作为输入的函数中 【参考方案1】:在您的 Playground 中查看我的 git hub 项目 // 马克西莫卢科西:https://github.com/lucosi/ChatTableView 您可以使用所有约束创建 tableViewCell 并更改单元格内的约束。 在 Playgournd > View > Assistant Editor > Show Assistant Editor 中打开项目
类 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)
]
)
扩展字符串
//* 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
//****** 自定义单元格类 ******/// 类 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")
【讨论】:
非常感谢。立即阅读并努力将其合并。敬请期待。 我在用我的数据库中的数组替换示例数据时遇到了一点问题。 现在当我查看对话并给出错误“无法将'__NSDictionaryM' (0x1128074f8) 类型的值转换为'Project.Message' (0x10f7f1478)”时它崩溃了。我有一个名为 loadMessages 的函数,它可以获取所有消息数据。 好的,我能够修复崩溃。但格式仍然全部向左对齐。 @teckgirl 我已尽力帮助您开发应用程序。现在您可以参考尝试解决代码中的问题。最好的;-)以上是关于在 Swift 中以编程方式将 UIImageView 左右对齐的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift 4 中以编程方式将 IBAction 添加到按钮?
在 Swift 4 中以编程方式将 UIImageView、UILabel 添加到 UIStackView
在 Swift 中以编程方式将 UIImageView 左右对齐
在 Swift 中以编程方式将视图添加到 stackview
当 iAd 横幅出现时,如何将视图的内容上移? (在 Swift 中以编程方式)
我想通过在 Swift 中以编程方式将 UINavigationController 与 UITableViewController 嵌入 UITableViewController 这是 UITab