Post

Replies

Boosts

Views

Activity

Is it possible to tweak collection view cell's layoutMarginsGuide when using compositional layout?
For UITableViewCells and UICollectionViewListCells, their contentView.layoutMarginsGuide respect the colletionView's layoutMarginsGuide automatically, which can be 16 or 20 points horizontally. This is the expected behavior. But for regular UICollectionViewCells with a regular compositional layout, their contentView.layoutMarginsGuide are defaulted to 8 points. I don't see where I can hook into and change the layout margins of the cells . I've looked into contentInset property and contentInsetReference property of section and item when constructing a compositional layout, but with no luck, their intentions are to change the width of the cells themselves.
1
0
630
Sep ’21
UICollectionView with diffable data source always reload on-screen cells after applying a snapshot.
From what I concluded, a diffable data source is designed to insert/delete/update/move only the differences from the new snapshot (if animatingDifferences is true), for those irrelevent cells, they should not be reloaded. But whenever I apply a snapshot, even if the new snapshot is exactly the current one from the data source, almost every on-screen cells got reloaded. Here's a simple test view controller: swift import UIKit class CollectionViewController: UIViewController {     enum Section: Hashable {         case main     }     struct Item: Hashable {         let id: String     }     private lazy var dataSource: UICollectionViewDiffableDataSourceSection, Item = {         return UICollectionViewDiffableDataSourceSection, Item(collectionView: collectionView) { collectionView, indexPath, item in             print("data source reloading cell", item, indexPath)             let cell =  collectionView.dequeueReusableCell(                 withReuseIdentifier: "cell",                 for: indexPath             ) as! Cell             cell.item = item             return cell         }     }()     private lazy var listLayout: UICollectionViewCompositionalLayout = {         let conf = UICollectionLayoutListConfiguration(appearance: .plain)         return UICollectionViewCompositionalLayout.list(using: conf)     }()     private lazy var regularLayout: UICollectionViewCompositionalLayout = {         let item = NSCollectionLayoutItem(             layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .estimated(50))         )         let group = NSCollectionLayoutGroup.horizontal(             layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .estimated(50)),             subitem: item,             count: 1         )         let section = NSCollectionLayoutSection(group: group)         return UICollectionViewCompositionalLayout(section: section)     }()     private lazy var collectionView: UICollectionView = {         let view = UICollectionView(frame: .zero, collectionViewLayout: regularLayout)         view.register(Cell.self, forCellWithReuseIdentifier: "cell")         view.translatesAutoresizingMaskIntoConstraints = false         view.backgroundColor = .systemBackground         return view     }()     override func viewDidLoad() {         super.viewDidLoad()         view.addSubview(collectionView)         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),         ])         var snapshot = NSDiffableDataSourceSnapshotSection, Item()         snapshot.appendSections([.main])         snapshot.appendItems((0 .. 100).map { .init(id: "\($0)") })         dataSource.apply(snapshot, animatingDifferences: false)         Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { _ in             print("\n\nDelayed Reloading")             var snapshot = self.dataSource.snapshot()             self.dataSource.apply(snapshot, animatingDifferences: true)         }     }     class Cell: UICollectionViewCell {         var item: Item? {             didSet {                 label.text = item?.id             }         }         private(set) lazy var label: UILabel = {             let view = UILabel()             view.font = .systemFont(ofSize: 48, weight: .semibold)             view.translatesAutoresizingMaskIntoConstraints = false             return view         }()         override init(frame: CGRect) {             super.init(frame: frame)             print("cell inited")             contentView.addSubview(label)             NSLayoutConstraint.activate([                 label.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor),                 label.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12),                 label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12),             ])         }         required init?(coder: NSCoder) {             fatalError("init(coder:) has not been implemented")         }     } } Output Xcode 12.5 iPhone 11 device (iOS 14.5.1) Delayed Reloading data source reloading cell Item(id: "2") [0, 2] data source reloading cell Item(id: "4") [0, 4] data source reloading cell Item(id: "6") [0, 6] data source reloading cell Item(id: "8") [0, 8] data source reloading cell Item(id: "10") [0, 10] data source reloading cell Item(id: "12") [0, 12] data source reloading cell Item(id: "14") [0, 14] data source reloading cell Item(id: "1") [0, 1] data source reloading cell Item(id: "3") [0, 3] data source reloading cell Item(id: "5") [0, 5] data source reloading cell Item(id: "7") [0, 7] data source reloading cell Item(id: "9") [0, 9] data source reloading cell Item(id: "11") [0, 11] data source reloading cell Item(id: "13") [0, 13] data source reloading cell Item(id: "15") [0, 15] data source reloading cell Item(id: "0") [0, 0] data source reloading cell Item(id: "11") [0, 11] Is this an expected behavior? I've also run the same test on UITableView, which is much more reasonable. Only some off-screen cells are reloaded.
2
0
4.4k
May ’21