Sample app
A collection view controller with list layout, 1 section and 1 row.
The cell's content view contains a text view.
class ViewController: UICollectionViewController {
var snapshot: NSDiffableDataSourceSnapshot<Section, String> {
var snapshot = NSDiffableDataSourceSnapshot<Section, String>()
snapshot.appendSections([.main])
snapshot.appendItems(["one", "two"], toSection: .main)
return snapshot
}
var dataSource: UICollectionViewDiffableDataSource<Section, String>?
enum Section {
case main
}
init() {
super.init(collectionViewLayout: .init())
collectionView.collectionViewLayout = createLayout()
configureDataSource() // more likely and automatically avoid unpleasant animations on iOS 15 by configuring the data source in the init rather than in view did load
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, String> { cell, indexPath, itemIdentifier in
let textView = UITextView()
textView.font = .systemFont(ofSize: UIFont.labelFontSize)
cell.contentView.addSubview(textView)
textView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
textView.topAnchor.constraint(equalTo: cell.contentView.topAnchor, constant: 8),
textView.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor, constant: -8),
textView.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor, constant: cell.directionalLayoutMargins.leading),
textView.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor, constant: -cell.directionalLayoutMargins.trailing)
])
}
dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in
collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier)
}
dataSource?.apply(self.snapshot, animatingDifferences: false)
}
func createLayout() -> UICollectionViewLayout {
return UICollectionViewCompositionalLayout { section, layoutEnvironment in
let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
return NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment)
}
}
}
Question 1
Can anybody edit the provided sample code so that the text view's vertical indicator inset is not cut off at the top?
Question 2
It seems to me that Apple has successfully implemented text views inside table view cells: can anybody provide Apple documentation as per how to do so?
What I've tried and didn't work
textView.verticalScrollIndicatorInsets.top = 30 // does nothing
- Adding the text view to a custom view and the view to the cell's content view
textView.contentInset = .zero
textView.scrollIndicatorInsets = .zero
textView.textContainerInset = .zero
textView.textContainer.lineFragmentPadding = 0
- Centering the text view vertically and constraining its height to that of the content view with an 8 points constant to leave some padding
- Constraining the top and bottom anchors of the text view to the cell's layout margins guide's top and bottom anchors
Constraint
I need the text view to have some padding from the top and bottom of the cell for aesthetic reasons.
Make the cell taller.
Updated cell registration:
let textView = UITextView()
textView.font = .systemFont(ofSize: UIFont.labelFontSize)
cell.contentView.addSubview(textView)
textView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
textView.centerYAnchor.constraint(equalTo: cell.contentView.centerYAnchor),
textView.heightAnchor.constraint(equalToConstant: textView.font!.pointSize * 4 - 16),
textView.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor, constant: cell.directionalLayoutMargins.leading),
textView.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor, constant: -cell.directionalLayoutMargins.trailing),
cell.contentView.heightAnchor.constraint(greaterThanOrEqualToConstant: textView.font!.pointSize * 4)
])