ios - 尝试将 Compositional Layout CollectionView 与 PageControl Hook 。 visibleItemsInvalidationHandler 未调用

标签 ios swift uipagecontrol uicollectionviewcompositionallayout

我想在 iOS 应用程序(iOS 13、swift 5.2、xcode 11.5)的欢迎屏幕上实现分页。

为此,我使用了 UICollectionView 和 UIPageControl。现在我需要将 pageControl 绑定(bind)到 Collection View 。

起初,我尝试使用 UIScrollViewDelegate,但很快发现它不适用于组合布局。 然后我发现了可用于组合布局部分的 visibleItemsInvalidationHandler。 我尝试了这样的不同选项:

section.visibleItemsInvalidationHandler = { (visibleItems, point, env) -> Void in
   self.pageControl.currentPage = visibleItems.last?.indexPath.row ?? 0 
}

像这样:

section.visibleItemsInvalidationHandler = { items, contentOffset, environment in
    let currentPage = Int(max(0, round(contentOffset.x / environment.container.contentSize.width)))
    self.pageControl.currentPage = currentPage
}

但没有任何作用...

似乎回调根本没有触发。如果我在其中放置打印语句,它不会执行。

完整代码如下:

import Foundation
import UIKit

class WelcomeVC: UIViewController, UICollectionViewDelegate {
    
    //MARK: - PROPERTIES
    var cardsDataSource: UICollectionViewDiffableDataSource<Int, WalkthroughCard>! = nil
    var cardsSnapshot = NSDiffableDataSourceSnapshot<Int, WalkthroughCard>()
    var cards: [WalkthroughCard]!
    var currentPage = 0
    
    
    //MARK: - OUTLETS
    @IBOutlet weak var signInButton: PrimaryButton!
    
    @IBOutlet weak var walkthroughCollectionView: UICollectionView!
    
    @IBOutlet weak var pageControl: UIPageControl!
    
    //MARK: - VIEW DID LOAD
    override func viewDidLoad() {
        super.viewDidLoad()
        walkthroughCollectionView.isScrollEnabled = true
        walkthroughCollectionView.delegate = self
        setupCards()
        pageControl.numberOfPages = cards.count
        configureCardsDataSource()
        configureCardsLayout()
    }
   
    //MARK: - SETUP CARDS
    
    func setupCards() {
        cards = [
            WalkthroughCard(title: "Welcome to abc", image: "Hello", description: "abc is an assistant to your xyz account at asdf"),
            WalkthroughCard(title: "Have all asdf projects at your fingertips", image: "Graphs", description: "Enjoy all project related data whithin a few taps. Even offline")
        ]
    }
    
    //MARK: - COLLECTION VIEW DIFFABLE DATA SOURCE
    
    private func configureCardsDataSource() {
        cardsDataSource = UICollectionViewDiffableDataSource<Int, WalkthroughCard>(collectionView: walkthroughCollectionView) {
            (collectionView: UICollectionView, indexPath: IndexPath, card: WalkthroughCard) -> UICollectionViewCell? in
            // Create cell
            guard let cell = collectionView.dequeueReusableCell(
                withReuseIdentifier: "WalkthroughCollectionViewCell",
                for: indexPath) as? WalkthroughCollectionViewCell else { fatalError("Cannot create new cell") }
            //cell.layer.cornerRadius = 15
            cell.walkthroughImage.image = UIImage(named: card.image)
            cell.walkthroughTitle.text = card.title
            cell.walkthroughDescription.text = card.description
            return cell
        }
        setupCardsSnapshot()
    }
    
    private func setupCardsSnapshot() {
        cardsSnapshot = NSDiffableDataSourceSnapshot<Int, WalkthroughCard>()
        cardsSnapshot.appendSections([0])
        cardsSnapshot.appendItems(cards)
        cardsDataSource.apply(self.cardsSnapshot, animatingDifferences: true)
    }
    
    
    //MARK: - CONFIGURE COLLECTION VIEW LAYOUT
    func configureCardsLayout() {
        walkthroughCollectionView.collectionViewLayout = generateCardsLayout()
    }
    
    func generateCardsLayout() -> UICollectionViewLayout {
        
        let itemSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1.0),
            heightDimension: .fractionalHeight(1.0))
        let fullPhotoItem = NSCollectionLayoutItem(layoutSize: itemSize)

        
        let groupSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1.0),
            heightDimension: .fractionalHeight(1.0))
        let group = NSCollectionLayoutGroup.horizontal(
            layoutSize: groupSize,
            subitem: fullPhotoItem,
            count: 1
        )
        
        let section = NSCollectionLayoutSection(group: group)
        section.orthogonalScrollingBehavior = .groupPagingCentered
        let layout = UICollectionViewCompositionalLayout(section: section)
        
        //setup pageControl
        section.visibleItemsInvalidationHandler = { (items, offset, env) -> Void in
            self.pageControl.currentPage = items.last?.indexPath.row ?? 0
        }
        
        return layout
    }
    
 
}

最佳答案

如果您在将部分传递给布局之前为该部分设置失效处理程序,它应该可以工作:

let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .groupPagingCentered
section.visibleItemsInvalidationHandler = { (items, offset, env) -> Void in
    self.pageControl.currentPage = items.last?.indexPath.row ?? 0
}

return UICollectionViewCompositionalLayout(section: section)

关于ios - 尝试将 Compositional Layout CollectionView 与 PageControl Hook 。 visibleItemsInvalidationHandler 未调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64081863/

相关文章:

iphone - UIPageControl 子类重写

ios - 无法访问 AppStore 连接

ios - 如何让动态 TableView 数据源更新 TableView ?

ios - 动态添加各种​​控件到scrollview(iOS/Swift)

swift - 如何检测 SwiftUI 中的点击手势位置?

ios - 当计数更多时,如何管理 UIPagecontrol 不超过 View 边界?

ios - 如何从iOS中旋转,缩放和倒置的UIImageView中提取UIImage

android - 在 ionic 框架中保存和加载应用程序

json - 如何使用 Swifty 动态创建具有多个键和值的 json 对象

ios - 在 Swift 中点击页面控件时更改页面