0 Replies
      Latest reply on Jan 10, 2020 2:53 PM by MCACH
      MCACH Level 1 Level 1 (0 points)

        I have searced far and wide and finally compared Apples WWDC example code. It seems evident that when adding UIScrollViewDelegate methods to the "Orthogonal Section Behaviours" example code, the delegates only get fired when scrolling vertically.

         

        Is this an expected behaviour and UIScrollViewDelegate is not supported horizontally by CompositionalLayout or is it something that will be addressed?

         

        /*
        See LICENSE folder for this sample’s licensing information.
        
        Abstract:
        Orthogonal scrolling section behaviors example
        */
        
        import UIKit
        
        class OrthogonalScrollBehaviorViewController: UIViewController {
            static let headerElementKind = "header-element-kind"
        
            enum SectionKind: Int, CaseIterable {
                case continuous, continuousGroupLeadingBoundary, paging, groupPaging, groupPagingCentered, none
                func orthogonalScrollingBehavior() -> UICollectionLayoutSectionOrthogonalScrollingBehavior {
                    switch self {
                    case .none:
                        return UICollectionLayoutSectionOrthogonalScrollingBehavior.none
                    case .continuous:
                        return UICollectionLayoutSectionOrthogonalScrollingBehavior.continuous
                    case .continuousGroupLeadingBoundary:
                        return UICollectionLayoutSectionOrthogonalScrollingBehavior.continuousGroupLeadingBoundary
                    case .paging:
                        return UICollectionLayoutSectionOrthogonalScrollingBehavior.paging
                    case .groupPaging:
                        return UICollectionLayoutSectionOrthogonalScrollingBehavior.groupPaging
                    case .groupPagingCentered:
                        return UICollectionLayoutSectionOrthogonalScrollingBehavior.groupPagingCentered
                    }
                }
            }
            var dataSource: UICollectionViewDiffableDataSource<Int, Int>! = nil
            var collectionView: UICollectionView! = nil
        
            override func viewDidLoad() {
                super.viewDidLoad()
                navigationItem.title = "Orthogonal Section Behaviors"
                configureHierarchy()
                configureDataSource()
            }
        }
        
        extension OrthogonalScrollBehaviorViewController {
        
            //   +-----------------------------------------------------+
            //   | +---------------------------------+  +-----------+  |
            //   | |                                 |  |           |  |
            //   | |                                 |  |           |  |
            //   | |                                 |  |     1     |  |
            //   | |                                 |  |           |  |
            //   | |                                 |  |           |  |
            //   | |                                 |  +-----------+  |
            //   | |               0                 |                 |
            //   | |                                 |  +-----------+  |
            //   | |                                 |  |           |  |
            //   | |                                 |  |           |  |
            //   | |                                 |  |     2     |  |
            //   | |                                 |  |           |  |
            //   | |                                 |  |           |  |
            //   | +---------------------------------+  +-----------+  |
            //   +-----------------------------------------------------+
        
            func createLayout() -> UICollectionViewLayout {
        
                let config = UICollectionViewCompositionalLayoutConfiguration()
                config.interSectionSpacing = 20
        
                let layout = UICollectionViewCompositionalLayout(sectionProvider: {
                    (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
                    guard let sectionKind = SectionKind(rawValue: sectionIndex) else { fatalError("unknown section kind") }
        
                    let leadingItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(
                        widthDimension: .fractionalWidth(0.7), heightDimension: .fractionalHeight(1.0)))
                    leadingItem.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10)
        
                    let trailingItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(
                        widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(0.3)))
                    trailingItem.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10)
                    let trailingGroup = NSCollectionLayoutGroup.vertical(layoutSize: NSCollectionLayoutSize(
                        widthDimension: .fractionalWidth(0.3), heightDimension: .fractionalHeight(1.0)),
                                                                         subitem: trailingItem,
                                                                         count: 2)
        
                    let orthogonallyScrolls = sectionKind.orthogonalScrollingBehavior() != .none
                    let containerGroupFractionalWidth = orthogonallyScrolls ? CGFloat(0.85) : CGFloat(1.0)
                    let containerGroup = NSCollectionLayoutGroup.horizontal(
                        layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(containerGroupFractionalWidth),
                                                          heightDimension: .fractionalHeight(0.4)),
                        subitems: [leadingItem, trailingGroup])
                    let section = NSCollectionLayoutSection(group: containerGroup)
                    section.orthogonalScrollingBehavior = sectionKind.orthogonalScrollingBehavior()
        
                    let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem(
                        layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                                          heightDimension: .estimated(44)),
                        elementKind: OrthogonalScrollBehaviorViewController.headerElementKind,
                        alignment: .top)
                    section.boundarySupplementaryItems = [sectionHeader]
                    return section
        
                }, configuration: config)
                return layout
            }
        }
        
        extension OrthogonalScrollBehaviorViewController {
            func configureHierarchy() {
                collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout())
                collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
                collectionView.backgroundColor = .systemBackground
                collectionView.register(TextCell.self, forCellWithReuseIdentifier: TextCell.reuseIdentifier)
                collectionView.register(ListCell.self, forCellWithReuseIdentifier: ListCell.reuseIdentifier)
                collectionView.register(
                    TitleSupplementaryView.self,
                    forSupplementaryViewOfKind: OrthogonalScrollBehaviorViewController.headerElementKind,
                    withReuseIdentifier: TitleSupplementaryView.reuseIdentifier)
                view.addSubview(collectionView)
                collectionView.delegate = self
            }
            func configureDataSource() {
                dataSource = UICollectionViewDiffableDataSource<Int, Int>(collectionView: collectionView) {
                    (collectionView: UICollectionView, indexPath: IndexPath, identifier: Int) -> UICollectionViewCell? in
        
                    // Get a cell of the desired kind.
                    guard let cell = collectionView.dequeueReusableCell(
                        withReuseIdentifier: TextCell.reuseIdentifier, for: indexPath) as? TextCell
                        else { fatalError("Cannot create new cell") }
        
                    // Populate the cell with our item description.
                    cell.label.text = "\(indexPath.section), \(indexPath.item)"
                    cell.contentView.backgroundColor = .cornflowerBlue
                    cell.contentView.layer.borderColor = UIColor.black.cgColor
                    cell.contentView.layer.borderWidth = 1
                    cell.contentView.layer.cornerRadius = 8
                    cell.label.textAlignment = .center
                    cell.label.font = UIFont.preferredFont(forTextStyle: .title1)
        
                    // Return the cell.
                    return cell
                }
                dataSource.supplementaryViewProvider = {
                    (collectionView: UICollectionView, kind: String, indexPath: IndexPath) -> UICollectionReusableView? in
                    guard let sectionKind = SectionKind(rawValue: indexPath.section)
                        else { fatalError("Unknown section kind") }
        
                    // Get a supplementary view of the desired kind.
                    if let header = collectionView.dequeueReusableSupplementaryView(
                        ofKind: kind,
                        withReuseIdentifier: TitleSupplementaryView.reuseIdentifier,
                        for: indexPath) as? TitleSupplementaryView {
        
                        // Populate the view with our section's description.
                        header.label.text = "." + String(describing: sectionKind)
        
                        // Return the view.
                        return header
                    } else {
                        fatalError("Cannot create new header")
                    }
                }
        
                // initial data
                var snapshot = NSDiffableDataSourceSnapshot<Int, Int>()
                var identifierOffset = 0
                let itemsPerSection = 18
                SectionKind.allCases.forEach {
                    snapshot.appendSections([$0.rawValue])
                    let maxIdentifier = identifierOffset + itemsPerSection
                    snapshot.appendItems(Array(identifierOffset..<maxIdentifier))
                    identifierOffset += itemsPerSection
                }
                dataSource.apply(snapshot, animatingDifferences: false)
            }
        }
        
        extension OrthogonalScrollBehaviorViewController: UICollectionViewDelegate {
            func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
                collectionView.deselectItem(at: indexPath, animated: true)
            }
            
            func scrollViewDidScroll(_ scrollView: UIScrollView) {
                   print("ScrollView decel rate: \(scrollView.decelerationRate)")
                   print("DidIt")
                   print("DidIt")
        
                   print("DidIt")
        
               }
               
               public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
                   print("Begin")
               }
               
               func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
                   print("End")
               }
               
                func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
                   print("END")
               }
        }