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
textView.contentInset = .zero
textView.scrollIndicatorInsets = .zero
textView.textContainerInset = .zero
textView.textContainer.lineFragmentPadding = 0
Constraint
I need the text view to have some padding from the top and bottom of the cell for aesthetic reasons.
The minimum height of the verticalScrollIndicator
is 36 ... plus 2-points from the top and 3-points from the bottom.
So you want the textView
height to be at least 41-points:
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),
// minimum height to show the full vertical scroll indicator
textView.heightAnchor.constraint(equalToConstant: 41.0),
])
If we use Debug View Hierarchy, we can inspect it (I set the text view background to yellow so we can see the framing):
When the app is running, we see this:
You don't want to use the font point size to calculate it...
Suppose the font size is 8.0? Or it's set to 40.0?
Presumably, you will know what size you're setting your font (after all, you're designing the app).
So if you're using a small-ish font - like .systemFont(ofSize: UIFont.labelFontSize)
- set the height to 41.0 (or greater, as desired).
If you're using a large font - like .systemFont(ofSize: 40.0)
- you'll almost certainly want to set the height greater than 41.0, or you won't see even one line of text.