Chat UI using UICollectionView

Words
667
Reading
3 min
Listen
Play
8y

What Will I Learn?

  • You will learn how to make a UICollectionView in swift.
  • You will learn how to use multiple cells in the UICollectionView.

Requirements

  • Xcode
  • Basic knowledge of Swift programming language.

Difficulty

  • Basic

Tutorial Contents

In this tutorial i am going to teach you how to make a Chat UI using UICollectionView. The collectionview contains to cells one for the sender and another for the reciever. When user sends the message the sender's cell will be used and when the message is recieved, the reciever's cell will be used in the collectionview.

First of all ope XCode and make a new project with Single View Application. Make a class ChatVC.swift which will contain all the code.

Now In Storyboard drag a UIViewController and name it ChatVC. In the controller drag a UICollectionView and make two cells in it. For first cell the reuse identifier will be SendersCell and for another one it will be RecieverCell.

Configure both the cells as shown in the image below

image.png

After making the UI of the collectionview let's go to ChatVC class. In this class make two outlets one for the collectionview and another for the textfield. Make a variable named messages which will hold all the incoming and outgoing messages. Make another outlet of UIButton which will be used to send message. Assign delegate and dataSourse of the collectionView to ChatVC.

@IBOutlet weak var chatDialogsCollectionVw : UICollectionView!
@IBOutlet weak var textField : UITextField!
@IBOutlet weak var sendMsgBtn : UIUIButton!

var messages = String

Make an extension of ChatVC and confirm to protocols UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout. Implement delegate and dataSource of the collectionview in the class.

The optional method of collectionView is numberOfSections which will automtically give it to 1. The number of items in the collectionview will be count of the massages array. Implement another dataSource method called cellForItemAtIndexPath. UICollectionViewDelegateFlowLayout contains methods for the size spacing between cells and section insets of the collection view as you can see below all of them are implemented.

extension ChatVC : UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

//MARK: UICollectionViewDataSource

func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.messages.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
     let  cell :MessageCell = collectionView.dequeueReusableCell(withReuseIdentifier: "RecieverCell", for: indexPath) as! MessageCell
        
        if let messageCell = cell {
            messageCell.layoutIfNeeded()
            messageCell.avtarImageVw.layer.cornerRadius = IsPad ? 40 : 30
            messageCell.avtarImageVw.clipsToBounds = true
            messageCell.text = message.meessageTextStr
            messageCell.dateSendLabel.text = message.dateSend
        }
        return cell!
}

//MARK: UICollectionViewDelegateFlowLayout

public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: 
  UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    var size = CGSize.zero
    let message = self.messages[indexPath.row]
   let attributedStr = NSMutableAttributedString.init(string: message.meessageTextStr)
    attributedStr.addAttributes([ NSAttributedStringKey.font : UIFont.systemFont(ofSize: 12) as Any], 
   range: NSRange.init(location: 0, length: attributedStr.length))
    let rect = attributedStr.boundingRect(with: CGSize.init(width: boundingWidth, height: 
   CGFloat.greatestFiniteMagnitude), options: NSStringDrawingOptions.usesLineFragmentOrigin, 
  context: nil)
  size = CGSize.init(width: self.chatCollectionVw.frame.size.width, height: rect.frame.size.height + 
 CGFloat(IsPad ? 120 : 100))
    
    return size
}

public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: 

UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets.init(top: 0, left: 0, bottom: collectionView.isEqual(self.chatCollectionVw) ? 70 : 0, right: 0)
}

public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 0
}

public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 0
}

}

I have made class of MessageCell to keep the logic behind so that it can be easily managed.

import UIKit

class MessageCell: UICollectionViewCell {

@IBOutlet weak var messgaeTextContainer : UIView!
@IBOutlet weak var avtarImageVw : UIImageView!
@IBOutlet weak var messageTextLabel : UILabel!
@IBOutlet weak var dateSendLabel : UILabel!

override func awakeFromNib() {
    super.awakeFromNib()
    self.messgaeTextContainer.layer.cornerRadius = 4.0
}

//MARK: Helpers

func configureCellWith(message :Message) {
    self.avtarImageVw.image = image
    self.messageTextLabel.text = message.meessageTextStr
    self.dateSendLabel.text = message.dateSend
}

}

This is the basic approach to implement all the necessary methods of the collectionview and get the things done. If you keep it on your way as simple as possible and run it it will look something like this

image.png



Posted on Utopian.io - Rewarding Open Source Contributors

Chat UI using UICollectionView | Ecency