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:

I found that there is a verticalAlignment property on "imageTextAttachment" that can be set for example to .top:
imageTextAttachment.verticalAlignment = .top
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()
}
}
