Align image inside DTImageTextAttachment

43 views Asked by At

I am trying to add an image to DTAttributedTextContentView and align it using DTImageTextAttachment like so:

 func addAndDisplayImage() {
     guard let image = UIImage(named: "test") else {
        print("Error loading image")
        return
     }
     imageTextAttachment.image = image.imageScaled(to: CGSize(width: 200, height: 200))
    
     let attributedString = NSAttributedString(attachment: imageTextAttachment)
     attributedTextContentView.attributedString = attributedString
    
     let rect: CGRect = attributedString.boundingRect(with: .init(width: 260.0, height: .greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil)
     widthConstraint.constant = ceil(rect.width)
     heightConstraint.constant = ceil(rect.height)

     layoutIfNeeded()
 }

However, the image is partially displayed. Here is the output: enter image description here

I found that there is a verticalAlignment property on "imageTextAttachment" that can be set for example to .top:

imageTextAttachment.verticalAlignment = .top

and the output will be this: enter image description here

But still it does not align image properly. Other values like .center, .bottom etc. also don't get the job done.

How to properly set the image so that it fits perfectly inside the attributedTextContentView?

Here is the full code:

import UIKit
import DTCoreText
class ViewController: UIViewController {
override func viewDidLoad() {
    super.viewDidLoad()
    configureCollectionView()
}

// MARK: - Collection view setup

let collectionView: UICollectionView = {
    let layout = UICollectionViewCompositionalLayout { (section, environment) -> NSCollectionLayoutSection? in
        let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(1))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        let group = NSCollectionLayoutGroup.vertical(layoutSize: itemSize, subitems: [item])
        let section = NSCollectionLayoutSection(group: group)
        section.interGroupSpacing = 5
        return section
    }
    layout.configuration.scrollDirection = .vertical
    let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)

    collectionView.register(ConversationCollectionViewCell.self, forCellWithReuseIdentifier: "ConversationCell")
    return collectionView
}()

private func configureCollectionView() {
    collectionView.dataSource = self
    collectionView.backgroundColor = .brown
    view.addSubview(collectionView)

    collectionView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        collectionView.topAnchor.constraint(equalTo: view.topAnchor),
        collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
    ])
}
}

// MARK: - Collection Data Source

  extension ViewController: UICollectionViewDataSource {
     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
   }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ConversationCell", for: indexPath) as! ConversationCollectionViewCell
        cell.addAndDisplayImage()
        return cell
   }
}

  final class ConversationCollectionViewCell: UICollectionViewCell, DTAttributedTextContentViewDelegate, DTLazyImageViewDelegate {

  let mainCellContainerView = UIView()
  let attributedTextContentView = DTAttributedTextContentView()
  let imageTextAttachment = DTImageTextAttachment()

  var widthConstraint: NSLayoutConstraint!
  var heightConstraint: NSLayoutConstraint!

   //MARK: - LIFECYCLE
    override init(frame: CGRect) {
       super.init(frame: frame)

       setupmainCellContainerView()
       setupAttributedTextContentView()
       layoutIfNeeded()
   }

   required init?(coder: NSCoder) {
       fatalError("init(coder:) has not been implemented")
   }

    // MARK: - UI STEUP

   private func setupmainCellContainerView() {
       contentView.addSubview(mainCellContainerView)
       mainCellContainerView.translatesAutoresizingMaskIntoConstraints = false

       NSLayoutConstraint.activate([
           mainCellContainerView.topAnchor.constraint(equalTo: contentView.topAnchor),
           mainCellContainerView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
           mainCellContainerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
           mainCellContainerView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
       ])
   }
   private func setupAttributedTextContentView() {
       mainCellContainerView.addSubview(attributedTextContentView)
    
       attributedTextContentView.delegate = self
       attributedTextContentView.backgroundColor = .systemIndigo
       attributedTextContentView.contentMode = .redraw
       attributedTextContentView.shouldDrawImages = true

       attributedTextContentView.translatesAutoresizingMaskIntoConstraints = false

       widthConstraint = attributedTextContentView.widthAnchor.constraint(lessThanOrEqualToConstant: 260.0)
       heightConstraint = attributedTextContentView.heightAnchor.constraint(equalToConstant: 80.0)
    
       NSLayoutConstraint.activate([
           widthConstraint,
           heightConstraint,
           attributedTextContentView.topAnchor.constraint(equalTo: mainCellContainerView.topAnchor),
           attributedTextContentView.bottomAnchor.constraint(equalTo: mainCellContainerView.bottomAnchor),
       ])
   }

   func addAndDisplayImage() {
       // Use image name from your assets
       guard let image = UIImage(named: "test") else {
           print("Error loading image")
           return
       }
       imageTextAttachment.image = image.imageScaled(to: CGSize(width: 200, height: 200))
    
       let attributedString = NSAttributedString(attachment: imageTextAttachment)
       attributedTextContentView.attributedString = attributedString
    
       imageTextAttachment.verticalAlignment = .top
       let rect: CGRect = attributedString.boundingRect(with: .init(width: 260.0, height: .greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil)
       widthConstraint.constant = ceil(rect.width)
       heightConstraint.constant = ceil(rect.height)
    
       layoutIfNeeded()
   }
 }
0

There are 0 answers