0

我目前正在研究水平画廊滚动视图。我决定使用启用水平分页的 UICollectionView。它几乎可以很好地工作...期望在旋转时集合视图单元格不居中(请参见随附的屏幕截图),其中红色是第一个单元格,黄色是第二个单元格。

在此处输入图像描述

它通常在第一次旋转时工作正常,但随后就搞砸了:D

这是我设置类的代码:

class GalleryScrollView: UIView {
    private var collectionView: UICollectionView!
    private var layout: UICollectionViewFlowLayout!
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupView()
    }

    override func layoutSubviews() {
        layout.invalidateLayout()
    }

    private func setupView() {
        layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        collectionView = UICollectionView(frame: self.frame,
                                          collectionViewLayout: layout)
        collectionView.register(UINib(nibName: "PhotoGalleryCell", bundle: nil), forCellWithReuseIdentifier: "photoGalleryCell")
        collectionView.isPagingEnabled = true
        collectionView.contentInsetAdjustmentBehavior = .never
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.autoresizingMask = .flexibleWidth
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.backgroundColor = .green
        self.addSubview(collectionView)

        NSLayoutConstraint.activate([
            collectionView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            collectionView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
            collectionView.topAnchor.constraint(equalTo: self.topAnchor),
            collectionView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
        ])

        collectionView.reloadData()
    }
}

其次是集合视图设置:

extension GalleryScrollView: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 0
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoGalleryCell", for: indexPath) as? PhotoGalleryCell else {
        return UICollectionViewCell()
    }

    if indexPath.item == 0 {
        cell.backgroundColor = .red
    } else {
        cell.backgroundColor = .yellow
    }

    return cell
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    2
}

func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    sizeForItemAt indexPath: IndexPath) -> CGSize {
    return self.frame.size
}

我试着玩弄,func collectionView(_ collectionView: UICollectionView, targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {但由于某种原因,函数从未被调用过。

有没有其他人遇到过这个问题?我在目标 c 线程中看到了很多主题,在 swift 中没有太多。我也有点难以理解为什么会发生这种情况,所以仅仅理解这个问题会非常有帮助。谢谢!

4

1 回答 1

1

你似乎没有处理旋转。reloadData当发生旋转时,您需要这样做。您将从那里获得事件,您UIViewController可以调用.reloadDataUICollectionView

class GalleryViewController: UIViewController {
    //...
    var galleryScrollView: GalleryScrollView
    //...
    override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
        super.willTransition(to: newCollection, with: coordinator)
        galleryScrollView.collectionViewLayout.invalidateLayout()
    }
    //...
}

然后在GalleryScrollView

class GalleryScrollView: UIView {
    var currentVisibleIndexPath = IndexPath(row: 0, section: 0)
    //....
}

extension GalleryScrollView: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    //...
    func collectionView(_ collectionView: UICollectionView, targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
        let attributes =  collectionView.layoutAttributesForItem(at: currentVisibleIndexPath)
        let newOriginForOldIndex = attributes?.frame.origin
        return newOriginForOldIndex ?? proposedContentOffset
    }

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

        let center = CGPoint(x: scrollView.contentOffset.x + (scrollView.frame.width / 2), y: (scrollView.frame.height / 2))
        if let indexPath = self.screenView.indexPathForItem(at: center) {
            currentVisibleIndexPath = indexPath
        }
    }
}
于 2020-07-30T11:32:34.800 回答