Использование Swift 5.1.3, iOS13.3,
Я пытаюсь отобразить горизонтальный CollectionViewController в качестве контроллера ChildView.
Проблема: все ячейки невидимы!
Печатная выписка в коде (показана с большим количеством !!!!!!!! в комментарии ниже)
Test.CardHeaderCell: 0x7fa563709370; baseClass = UICollectionViewCell; frame = (1059 23; 343 279); hidden = YES; layer = <CALayer: 0x6000024de080>>
Вот код:
override func viewDidLoad() {
// ...
let cardsHorizontalController = CardsHorizontalController()
self.addChild(cardsHorizontalController)
self.view.addSubview(cardsHorizontalController.view)
self.didMove(toParent: cardsHorizontalController)
cardsHorizontalController.view.translatesAutoresizingMaskIntoConstraints = false
cardsHorizontalController.view.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 70.0).isActive = true
cardsHorizontalController.view.heightAnchor.constraint(equalToConstant: 390.0).isActive = true
cardsHorizontalController.view.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width).isActive = true
}
Вот горизонтальный контроллер
class CardsHorizontalController: HorizontalSnappingController, UICollectionViewDelegateFlowLayout {
let cellId = "horizontalCardID"
override func viewDidLoad() {
super.viewDidLoad()
collectionView.backgroundColor = .green
collectionView.register(CardHeaderCell.self, forCellWithReuseIdentifier: cellId)
if let layout = collectionViewLayout as? UICollectionViewFlowLayout {
layout.scrollDirection = .horizontal
}
collectionView.showsHorizontalScrollIndicator = true
collectionView.showsVerticalScrollIndicator = false
// do the insets here instead of the optional "insetForSectionAt" delegate-method
// i.e. this helps to get the scrolled cells aligned in the middle of the screen once 1 cell wide scrolled...
collectionView.contentInset = .init(top: 65.0, left: 16.0, bottom: 0.0, right: 16.0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return .init(width: view.frame.width - 32.0, height: 279.0)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 17
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
print(cell)
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
return cell
}
}
и ячейка:
class CardHeaderCell: UICollectionViewCell {
let imageView = UIImageView(cornerRadius: 10.0)
override init(frame: CGRect) {
super.init(frame: frame)
// blur view
imageView.backgroundColor = UIColor(red: 0.086, green: 0.086, blue: 0.086, alpha: 0.35)
let visualEffectView = UIVisualEffectView(frame: imageView.frame)
visualEffectView.effect = UIView.customBlurEffect()
visualEffectView.autoresizingMask = UIView.AutoresizingMask(rawValue: UIView.AutoresizingMask.flexibleWidth.rawValue | UIView.AutoresizingMask.flexibleHeight.rawValue)
imageView.addSubview(visualEffectView)
let stackView = VerticalStackView(arrangedSubviews: [
imageView
], spacing: 12.0)
addSubview(stackView)
stackView.fillSuperview(padding: .init(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0))
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
}
А по соображениям полноты здесь остальные пользовательские классы ...
class HorizontalSnappingController: UICollectionViewController {
init() {
let layout = BetterSnappingLayout()
layout.scrollDirection = .horizontal
super.init(collectionViewLayout: layout)
collectionView.decelerationRate = .fast
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class BetterSnappingLayout: UICollectionViewFlowLayout {
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
guard let collectionView = collectionView else {
return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity)
}
let nextX: CGFloat
if proposedContentOffset.x <= 0 || collectionView.contentOffset == proposedContentOffset {
nextX = proposedContentOffset.x
} else {
nextX = collectionView.contentOffset.x + (velocity.x > 0 ? collectionView.bounds.size.width : -collectionView.bounds.size.width)
}
let targetRect = CGRect(x: nextX, y: 0, width: collectionView.bounds.size.width, height: collectionView.bounds.size.height)
var offsetAdjustment = CGFloat.greatestFiniteMagnitude
let horizontalOffset = proposedContentOffset.x + collectionView.contentInset.left
let layoutAttributesArray = super.layoutAttributesForElements(in: targetRect)
layoutAttributesArray?.forEach({ (layoutAttributes) in
let itemOffset = layoutAttributes.frame.origin.x
if fabsf(Float(itemOffset - horizontalOffset)) < fabsf(Float(offsetAdjustment)) {
offsetAdjustment = itemOffset - horizontalOffset
}
})
return CGPoint(x: proposedContentOffset.x + offsetAdjustment, y: proposedContentOffset.y)
}
}
class VerticalStackView: UIStackView {
init(arrangedSubviews: [UIView], spacing: CGFloat = 0, alignment: UIStackView.Alignment = .center) {
super.init(frame: .zero)
arrangedSubviews.forEach({addArrangedSubview($0)})
self.spacing = spacing
self.alignment = alignment
self.axis = .vertical
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}